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

Reply via email to