|
15 | 15 | #include <mongocxx/instance.hpp> |
16 | 16 |
|
17 | 17 | #include <mutex> |
| 18 | +#include <type_traits> |
18 | 19 | #include <utility> |
19 | 20 |
|
20 | 21 | #include <bsoncxx/stdx/make_unique.hpp> |
@@ -60,9 +61,10 @@ void user_log_handler(::mongoc_log_level_t mongoc_log_level, const char *log_dom |
60 | 61 | stdx::string_view{log_domain}, stdx::string_view{message}); |
61 | 62 | } |
62 | 63 |
|
63 | | -std::recursive_mutex instance_mutex; |
64 | | -instance *current_instance = nullptr; |
65 | | -std::unique_ptr<instance> global_instance; |
| 64 | +std::atomic<instance*> current_instance{nullptr}; |
| 65 | +static_assert(std::is_standard_layout<decltype(current_instance)>::value, "Must be standard layout"); |
| 66 | +static_assert(std::is_trivially_constructible<decltype(current_instance)>::value, "Must be trivially constructible"); |
| 67 | +static_assert(std::is_trivially_destructible<decltype(current_instance)>::value, "Must be trivially destructible"); |
66 | 68 |
|
67 | 69 | } // namespace |
68 | 70 |
|
@@ -94,31 +96,25 @@ instance::instance() : instance(nullptr) { |
94 | 96 | } |
95 | 97 |
|
96 | 98 | instance::instance(std::unique_ptr<logger> logger) { |
97 | | - std::lock_guard<std::recursive_mutex> lock(instance_mutex); |
98 | | - if (current_instance) { |
| 99 | + instance* expected = nullptr; |
| 100 | + if (!current_instance.compare_exchange_strong(expected, this)) |
99 | 101 | throw logic_error{error_code::k_instance_already_exists}; |
100 | | - } |
101 | 102 | _impl = stdx::make_unique<impl>(std::move(logger)); |
102 | | - current_instance = this; |
103 | 103 | } |
104 | 104 |
|
105 | 105 | instance::instance(instance &&) noexcept = default; |
106 | 106 | instance &instance::operator=(instance &&) noexcept = default; |
107 | 107 |
|
108 | 108 | instance::~instance() { |
109 | | - std::lock_guard<std::recursive_mutex> lock(instance_mutex); |
110 | | - if (current_instance != this) std::abort(); |
111 | 109 | _impl.reset(); |
112 | | - current_instance = nullptr; |
| 110 | + current_instance.store(nullptr); |
113 | 111 | } |
114 | 112 |
|
115 | 113 | instance &instance::current() { |
116 | | - std::lock_guard<std::recursive_mutex> lock(instance_mutex); |
117 | | - if (!current_instance) { |
118 | | - global_instance.reset(new instance); |
119 | | - current_instance = global_instance.get(); |
| 114 | + if (!current_instance.load()) { |
| 115 | + static instance the_instance; |
120 | 116 | } |
121 | | - return *current_instance; |
| 117 | + return *current_instance.load(); |
122 | 118 | } |
123 | 119 |
|
124 | 120 | MONGOCXX_INLINE_NAMESPACE_END |
|
0 commit comments