https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116843
Bug ID: 116843 Summary: Native platform wait on Windows Product: gcc Version: 15.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- Target: *-w64-mingw32 Copied from Bug 107886 comment 15 and Bug 107886 comment 16: we might be able to support some subset of C++20 concurrency primitives for the Win32 model. As https://github.com/luncliff/latch/blob/master/latch_windows.cpp shows all that's needed are atomic decrements and WaitOnAddress/WakeByAddressAll. If our std::__atomic_wait_address and __atomic_impl::notify_all used those, we could provide std::latch, and maybe others. Something like ... --- include/bits/atomic_wait.h 2022-11-07 15:38:32.551751184 +0000 +++ /tmp/inc/bits/atomic_wait.h 2022-11-28 16:27:51.352489618 +0000 @@ -33,7 +33,7 @@ #pragma GCC system_header #include <bits/c++config.h> -#if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX +#if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX || _WIN32 #include <bits/functional_hash.h> #include <bits/gthr.h> #include <ext/numeric_traits.h> @@ -59,6 +59,10 @@ #define _GLIBCXX_HAVE_PLATFORM_WAIT 1 using __platform_wait_t = int; inline constexpr size_t __platform_wait_alignment = 4; +#elif _WIN32 + using __platform_wait_t = __UINTPTR_TYPE__; + inline constexpr size_t __platform_wait_alignment + = alignof(__platform_wait_t); #else // define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait() // and __platform_notify() if there is a more efficient primitive supported @@ -122,6 +126,30 @@ static_cast<int>(__futex_wait_flags::__wake_private), __all ? INT_MAX : 1); } +#elif _WIN32 + extern "C" int __glibcxx_get_last_error() __asm("GetLastError"); + + template<typename _Tp> + void + __platform_wait(const _Tp* __addr, __platform_wait_t __val) noexcept + { + const long __timeout = 0xffffffff; + if (WaitOnAddress(__addr, &__val, sizeof(__platform_wait_t), __timeout)) + return; + _GLIBCXX_THROW_OR_ABORT(std::system_error(__glibcxx_get_last_error(), + std::system_category(), + "WaitOnAddress")); + } + + template<typename _Tp> + void + __platform_notify(const _Tp* __addr, bool __all) noexcept + { + if (__all) + WakeByAddressAll(__addr); + else + WakeByAddressOne(__addr); + } #endif inline void