2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
6 * Copyright (c) 2020 Andrey Semashev
9 * \file wait_on_address.cpp
11 * This file contains implementation of runtime detection of \c WaitOnAddress and related APIs on Windows.
13 * https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
14 * https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddresssingle
15 * https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-wakebyaddressall
18 // Include boost/winapi/config.hpp first to make sure target Windows version is selected by Boost.WinAPI
19 #include <boost/winapi/config.hpp>
21 #include <boost/winapi/basic_types.hpp>
23 #include <boost/atomic/detail/config.hpp>
24 #include <boost/atomic/detail/link.hpp>
25 #include <boost/atomic/detail/once_flag.hpp>
26 #include <boost/atomic/detail/wait_on_address.hpp>
28 #if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
30 #include <boost/static_assert.hpp>
31 #include <boost/memory_order.hpp>
32 #include <boost/winapi/thread.hpp>
33 #include <boost/winapi/get_proc_address.hpp>
34 #include <boost/winapi/dll.hpp>
36 #include <boost/atomic/detail/core_operations.hpp>
38 #endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
40 #include <boost/atomic/detail/header.hpp>
46 BOOST_ATOMIC_DECL wait_on_address_t
* wait_on_address
= NULL
;
47 BOOST_ATOMIC_DECL wake_by_address_t
* wake_by_address_single
= NULL
;
48 BOOST_ATOMIC_DECL wake_by_address_t
* wake_by_address_all
= NULL
;
50 #if BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
52 BOOST_ATOMIC_DECL once_flag wait_functions_once_flag
= { 2u };
54 BOOST_ATOMIC_DECL
void initialize_wait_functions() BOOST_NOEXCEPT
56 BOOST_STATIC_ASSERT_MSG(once_flag_operations::is_always_lock_free
, "Boost.Atomic unsupported target platform: native atomic operations not implemented for bytes");
58 once_flag_operations::storage_type old_val
= once_flag_operations::load(wait_functions_once_flag
.m_flag
, boost::memory_order_acquire
);
63 if (BOOST_UNLIKELY(!once_flag_operations::compare_exchange_strong(wait_functions_once_flag
.m_flag
, old_val
, 1u, boost::memory_order_relaxed
, boost::memory_order_relaxed
)))
66 boost::winapi::HMODULE_ kernel_base
= boost::winapi::get_module_handle(L
"api-ms-win-core-synch-l1-2-0.dll");
67 if (BOOST_LIKELY(kernel_base
!= NULL
))
69 wait_on_address_t
* woa
= (wait_on_address_t
*)boost::winapi::get_proc_address(kernel_base
, "WaitOnAddress");
70 if (BOOST_LIKELY(woa
!= NULL
))
72 wake_by_address_t
* wbas
= (wake_by_address_t
*)boost::winapi::get_proc_address(kernel_base
, "WakeByAddressSingle");
73 wake_by_address_t
* wbaa
= (wake_by_address_t
*)boost::winapi::get_proc_address(kernel_base
, "WakeByAddressAll");
75 if (BOOST_LIKELY(wbas
!= NULL
&& wbaa
!= NULL
))
77 wait_on_address
= woa
;
78 wake_by_address_single
= wbas
;
79 wake_by_address_all
= wbaa
;
84 once_flag_operations::store(wait_functions_once_flag
.m_flag
, 0u, boost::memory_order_release
);
87 else if (old_val
== 1u)
89 boost::winapi::SwitchToThread();
90 old_val
= once_flag_operations::load(wait_functions_once_flag
.m_flag
, boost::memory_order_acquire
);
99 #else // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
101 BOOST_ATOMIC_DECL once_flag wait_functions_once_flag
= { 0u };
103 BOOST_ATOMIC_DECL
void initialize_wait_functions() BOOST_NOEXCEPT
107 #endif // BOOST_WINAPI_PARTITION_DESKTOP || BOOST_WINAPI_PARTITION_SYSTEM
109 } // namespace detail
110 } // namespace atomics
113 #include <boost/atomic/detail/footer.hpp>