10
10
11
11
#include < Windows.h>
12
12
13
+ #pragma comment(lib, "synchronization")
14
+
13
15
namespace {
14
16
constexpr unsigned long long _Atomic_wait_no_deadline = 0xFFFF'FFFF'FFFF'FFFF ;
15
17
@@ -89,120 +91,6 @@ namespace {
89
91
#endif // defined(_DEBUG)
90
92
}
91
93
92
- #ifndef _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
93
- #if _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8
94
- #define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 1
95
- #else // ^^^ _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 vvv
96
- #define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 0
97
- #endif // ^^^ _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 ^^^
98
- #endif // !defined(_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE)
99
-
100
- #if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
101
-
102
- #pragma comment(lib, "synchronization")
103
-
104
- #define __crtWaitOnAddress WaitOnAddress
105
- #define __crtWakeByAddressSingle WakeByAddressSingle
106
- #define __crtWakeByAddressAll WakeByAddressAll
107
-
108
- #else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv
109
-
110
- struct _Wait_functions_table {
111
- _STD atomic<decltype (&::WaitOnAddress)> _Pfn_WaitOnAddress{nullptr };
112
- _STD atomic<decltype (&::WakeByAddressSingle)> _Pfn_WakeByAddressSingle{nullptr };
113
- _STD atomic<decltype (&::WakeByAddressAll)> _Pfn_WakeByAddressAll{nullptr };
114
- _STD atomic<__std_atomic_api_level> _Api_level{__std_atomic_api_level::__not_set};
115
- };
116
-
117
- _Wait_functions_table _Wait_functions;
118
-
119
- void _Force_wait_functions_srwlock_only () noexcept {
120
- auto _Local = _Wait_functions._Api_level .load (_STD memory_order_acquire);
121
- if (_Local <= __std_atomic_api_level::__detecting) {
122
- while (!_Wait_functions._Api_level .compare_exchange_weak (
123
- _Local, __std_atomic_api_level::__has_srwlock, _STD memory_order_acq_rel)) {
124
- if (_Local > __std_atomic_api_level::__detecting) {
125
- return ;
126
- }
127
- }
128
- }
129
- }
130
-
131
- [[nodiscard]] __std_atomic_api_level _Init_wait_functions (__std_atomic_api_level _Level) {
132
- while (!_Wait_functions._Api_level .compare_exchange_weak (
133
- _Level, __std_atomic_api_level::__detecting, _STD memory_order_acq_rel)) {
134
- if (_Level > __std_atomic_api_level::__detecting) {
135
- return _Level;
136
- }
137
- }
138
-
139
- _Level = __std_atomic_api_level::__has_srwlock;
140
-
141
- const HMODULE _Sync_module = GetModuleHandleW (L" api-ms-win-core-synch-l1-2-0.dll" );
142
- if (_Sync_module != nullptr ) {
143
- const auto _Wait_on_address =
144
- reinterpret_cast <decltype (&::WaitOnAddress)>(GetProcAddress (_Sync_module, " WaitOnAddress" ));
145
- const auto _Wake_by_address_single =
146
- reinterpret_cast <decltype (&::WakeByAddressSingle)>(GetProcAddress (_Sync_module, " WakeByAddressSingle" ));
147
- const auto _Wake_by_address_all =
148
- reinterpret_cast <decltype (&::WakeByAddressAll)>(GetProcAddress (_Sync_module, " WakeByAddressAll" ));
149
-
150
- if (_Wait_on_address != nullptr && _Wake_by_address_single != nullptr && _Wake_by_address_all != nullptr ) {
151
- _Wait_functions._Pfn_WaitOnAddress .store (_Wait_on_address, _STD memory_order_relaxed);
152
- _Wait_functions._Pfn_WakeByAddressSingle .store (_Wake_by_address_single, _STD memory_order_relaxed);
153
- _Wait_functions._Pfn_WakeByAddressAll .store (_Wake_by_address_all, _STD memory_order_relaxed);
154
- _Level = __std_atomic_api_level::__has_wait_on_address;
155
- }
156
- }
157
-
158
- // for __has_srwlock, relaxed would have been enough, not distinguishing for consistency
159
- _Wait_functions._Api_level .store (_Level, _STD memory_order_release);
160
- return _Level;
161
- }
162
-
163
- [[nodiscard]] __std_atomic_api_level _Acquire_wait_functions () noexcept {
164
- auto _Level = _Wait_functions._Api_level .load (_STD memory_order_acquire);
165
- if (_Level <= __std_atomic_api_level::__detecting) {
166
- _Level = _Init_wait_functions (_Level);
167
- }
168
-
169
- return _Level;
170
- }
171
-
172
- [[nodiscard]] BOOL __crtWaitOnAddress (
173
- volatile VOID* Address, PVOID CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds) {
174
- const auto _Wait_on_address = _Wait_functions._Pfn_WaitOnAddress .load (_STD memory_order_relaxed);
175
- return _Wait_on_address (Address, CompareAddress, AddressSize, dwMilliseconds);
176
- }
177
-
178
- VOID __crtWakeByAddressSingle (PVOID Address) {
179
- const auto _Wake_by_address_single = _Wait_functions._Pfn_WakeByAddressSingle .load (_STD memory_order_relaxed);
180
- _Wake_by_address_single (Address);
181
- }
182
-
183
- VOID __crtWakeByAddressAll (PVOID Address) {
184
- const auto _Wake_by_address_all = _Wait_functions._Pfn_WakeByAddressAll .load (_STD memory_order_relaxed);
185
- _Wake_by_address_all (Address);
186
- }
187
-
188
- bool __stdcall _Atomic_wait_are_equal_direct_fallback (
189
- const void * _Storage, void * _Comparand, size_t _Size, void *) noexcept {
190
- switch (_Size) {
191
- case 1 :
192
- return __iso_volatile_load8 (static_cast <const char *>(_Storage)) == *static_cast <const char *>(_Comparand);
193
- case 2 :
194
- return __iso_volatile_load16 (static_cast <const short *>(_Storage)) == *static_cast <const short *>(_Comparand);
195
- case 4 :
196
- return __iso_volatile_load32 (static_cast <const int *>(_Storage)) == *static_cast <const int *>(_Comparand);
197
- case 8 :
198
- return __iso_volatile_load64 (static_cast <const long long *>(_Storage))
199
- == *static_cast <const long long *>(_Comparand);
200
- default :
201
- _CSTD abort ();
202
- }
203
- }
204
- #endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
205
-
206
94
[[nodiscard]] unsigned char __std_atomic_compare_exchange_128_fallback (
207
95
_Inout_bytecount_ (16 ) long long* _Destination, _In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
208
96
_Inout_bytecount_(16 ) long long* _ComparandResult) noexcept {
@@ -225,15 +113,8 @@ namespace {
225
113
extern " C" {
226
114
int __stdcall __std_atomic_wait_direct (const void * const _Storage, void * const _Comparand, const size_t _Size,
227
115
const unsigned long _Remaining_timeout) noexcept {
228
- #if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
229
- if (_Acquire_wait_functions () < __std_atomic_api_level::__has_wait_on_address) {
230
- return __std_atomic_wait_indirect (
231
- _Storage, _Comparand, _Size, nullptr , &_Atomic_wait_are_equal_direct_fallback, _Remaining_timeout);
232
- }
233
- #endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
234
-
235
- const auto _Result = __crtWaitOnAddress (
236
- const_cast <volatile void *>(_Storage), const_cast <void *>(_Comparand), _Size, _Remaining_timeout);
116
+ const auto _Result =
117
+ WaitOnAddress (const_cast <volatile void *>(_Storage), const_cast <void *>(_Comparand), _Size, _Remaining_timeout);
237
118
238
119
if (!_Result) {
239
120
_Assume_timeout ();
@@ -242,25 +123,11 @@ int __stdcall __std_atomic_wait_direct(const void* const _Storage, void* const _
242
123
}
243
124
244
125
void __stdcall __std_atomic_notify_one_direct (const void * const _Storage) noexcept {
245
- #if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
246
- if (_Acquire_wait_functions () < __std_atomic_api_level::__has_wait_on_address) {
247
- __std_atomic_notify_one_indirect (_Storage);
248
- return ;
249
- }
250
- #endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE = 0
251
-
252
- __crtWakeByAddressSingle (const_cast <void *>(_Storage));
126
+ WakeByAddressSingle (const_cast <void *>(_Storage));
253
127
}
254
128
255
129
void __stdcall __std_atomic_notify_all_direct (const void * const _Storage) noexcept {
256
- #if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
257
- if (_Acquire_wait_functions () < __std_atomic_api_level::__has_wait_on_address) {
258
- __std_atomic_notify_all_indirect (_Storage);
259
- return ;
260
- }
261
- #endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
262
-
263
- __crtWakeByAddressAll (const_cast <void *>(_Storage));
130
+ WakeByAddressAll (const_cast <void *>(_Storage));
264
131
}
265
132
266
133
void __stdcall __std_atomic_notify_one_indirect (const void * const _Storage) noexcept {
@@ -356,25 +223,10 @@ unsigned long __stdcall __std_atomic_wait_get_remaining_timeout(unsigned long lo
356
223
return static_cast <unsigned long >(_Remaining);
357
224
}
358
225
359
- __std_atomic_api_level __stdcall __std_atomic_set_api_level (__std_atomic_api_level _Requested_api_level) noexcept {
360
- # if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
361
- ( void ) _Requested_api_level;
226
+ // TRANSITION, ABI: preserved for binary compatibility
227
+ enum class __std_atomic_api_level : unsigned long { __not_set, __detecting, __has_srwlock, __has_wait_on_address };
228
+ __std_atomic_api_level __stdcall __std_atomic_set_api_level (__std_atomic_api_level) noexcept {
362
229
return __std_atomic_api_level::__has_wait_on_address;
363
- #else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv
364
- switch (_Requested_api_level) {
365
- case __std_atomic_api_level::__not_set:
366
- case __std_atomic_api_level::__detecting:
367
- _CSTD abort ();
368
- case __std_atomic_api_level::__has_srwlock:
369
- _Force_wait_functions_srwlock_only ();
370
- break ;
371
- case __std_atomic_api_level::__has_wait_on_address:
372
- default : // future compat: new header using an old DLL will get the highest requested level supported
373
- break ;
374
- }
375
-
376
- return _Acquire_wait_functions ();
377
- #endif // !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
378
230
}
379
231
380
232
#pragma warning(push)
0 commit comments