Skip to content

Commit b793a00

Browse files
committed
Use a spin lock instead of a mutex in __instance_data
Hoping that msvc will allow it to be `constinit`.
1 parent 0242420 commit b793a00

1 file changed

Lines changed: 16 additions & 7 deletions

File tree

include/exec/__detail/__system_context_default_impl.hpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ namespace exec::__system_context_default_impl {
219219
/// Gets the current instance; if there is no instance, uses the current factory to create one.
220220
std::shared_ptr<_Interface> __get_current_instance() {
221221
// If we have a valid instance, return it.
222-
__instance_mutex_.lock();
222+
__acquire_instance_lock();
223223
auto __r = __instance_;
224-
__instance_mutex_.unlock();
224+
__release_instance_lock();
225225
if (__r) {
226226
return __r;
227227
}
@@ -231,9 +231,9 @@ namespace exec::__system_context_default_impl {
231231
auto __new_instance = __factory_.load(std::memory_order_relaxed)();
232232

233233
// Store the newly created instance.
234-
__instance_mutex_.lock();
234+
__acquire_instance_lock();
235235
__instance_ = __new_instance;
236-
__instance_mutex_.unlock();
236+
__release_instance_lock();
237237
return __new_instance;
238238
}
239239

@@ -245,23 +245,32 @@ namespace exec::__system_context_default_impl {
245245
// Create a new instance with the new factory.
246246
auto __new_instance = __new_factory();
247247
// Replace the current instance with the new one.
248-
__instance_mutex_.lock();
248+
__acquire_instance_lock();
249249
auto __old_instance = std::exchange(__instance_, __new_instance);
250-
__instance_mutex_.unlock();
250+
__release_instance_lock();
251251
// Make sure to delete the old instance after releasing the lock.
252252
__old_instance.reset();
253253
return __old_factory;
254254
}
255255

256256
private:
257-
std::mutex __instance_mutex_{};
257+
std::atomic<bool> __instance_locked_{false};
258258
std::shared_ptr<_Interface> __instance_{nullptr};
259259
std::atomic<__system_context_backend_factory<_Interface>> __factory_{__default_factory};
260260

261261
/// The default factory returns an instance of `_Impl`.
262262
static std::shared_ptr<_Interface> __default_factory() {
263263
return std::make_shared<_Impl>();
264264
}
265+
266+
void __acquire_instance_lock() {
267+
while (__instance_locked_.exchange(true, std::memory_order_acquire)) {
268+
// Spin until we acquire the lock.
269+
}
270+
}
271+
void __release_instance_lock() {
272+
__instance_locked_.store(false, std::memory_order_release);
273+
}
265274
};
266275

267276
#if STDEXEC_ENABLE_LIBDISPATCH

0 commit comments

Comments
 (0)