diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 057d5b548..c901b94ba 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -146,32 +146,42 @@ WINRT_EXPORT namespace winrt void set_canceller(canceller_t canceller, void* context) { m_context = context; - m_canceller.store(canceller, std::memory_order_release); + canceller_t expected = nullptr; + m_canceller.compare_exchange_strong(expected, canceller, std::memory_order_release, std::memory_order_relaxed); } void revoke_canceller() { - while (m_canceller.exchange(nullptr, std::memory_order_acquire) == cancelling_ptr) + auto existing = m_canceller.load(std::memory_order_relaxed); + do { - std::this_thread::yield(); + while (existing == cancelling_ptr) + { + std::this_thread::yield(); + existing = m_canceller.load(std::memory_order_relaxed); + } } + while (!m_canceller.compare_exchange_weak(existing, nullptr, std::memory_order_acquire, std::memory_order_relaxed)); } void cancel() { auto canceller = m_canceller.exchange(cancelling_ptr, std::memory_order_acquire); - struct unique_cancellation_lock + if (canceller != cancelling_ptr) { - cancellable_promise* promise; - ~unique_cancellation_lock() + struct unique_cancellation_lock + { + cancellable_promise* promise; + ~unique_cancellation_lock() + { + promise->m_canceller.store(nullptr, std::memory_order_release); + } + } lock{ this }; + + if (canceller != nullptr) { - promise->m_canceller.store(nullptr, std::memory_order_release); + canceller(m_context); } - } lock{ this }; - - if ((canceller != nullptr) && (canceller != cancelling_ptr)) - { - canceller(m_context); } } diff --git a/strings/base_includes.h b/strings/base_includes.h index 287a09709..bac7358bd 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/strings/base_macros.h b/strings/base_macros.h index 91b0121d9..850d0c627 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -44,7 +44,7 @@ // Template specializations in namespace std (hash, coroutine_traits) need extern "C++" // linkage in module builds for proper merging with the std module, but must NOT be -// exported — exporting namespace std would make all of std transitively visible. +// exported - exporting namespace std would make all of std transitively visible. #ifndef WINRT_IMPL_STD_EXPORT #ifdef WINRT_IMPL_BUILD_MODULE #define WINRT_IMPL_STD_EXPORT extern "C++"