Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/13/bits/atomic_timed_wait.h
$ cat -n /usr/include/c++/13/bits/atomic_timed_wait.h 1 // -*- C++ -*- header. 2 3 // Copyright (C) 2020-2023 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 //
. 24 25 /** @file bits/atomic_timed_wait.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{atomic} 28 */ 29 30 #ifndef _GLIBCXX_ATOMIC_TIMED_WAIT_H 31 #define _GLIBCXX_ATOMIC_TIMED_WAIT_H 1 32 33 #pragma GCC system_header 34 35 #include
36 37 #if __cpp_lib_atomic_wait 38 #include
39 #include
40 #include
41 42 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX 43 #include
44 #endif 45 46 namespace std _GLIBCXX_VISIBILITY(default) 47 { 48 _GLIBCXX_BEGIN_NAMESPACE_VERSION 49 50 namespace __detail 51 { 52 using __wait_clock_t = chrono::steady_clock; 53 54 template
55 __wait_clock_t::time_point 56 __to_wait_clock(const chrono::time_point<_Clock, _Dur>& __atime) noexcept 57 { 58 const typename _Clock::time_point __c_entry = _Clock::now(); 59 const __wait_clock_t::time_point __w_entry = __wait_clock_t::now(); 60 const auto __delta = __atime - __c_entry; 61 using __w_dur = typename __wait_clock_t::duration; 62 return __w_entry + chrono::ceil<__w_dur>(__delta); 63 } 64 65 template
66 __wait_clock_t::time_point 67 __to_wait_clock(const chrono::time_point<__wait_clock_t, 68 _Dur>& __atime) noexcept 69 { 70 using __w_dur = typename __wait_clock_t::duration; 71 return chrono::ceil<__w_dur>(__atime); 72 } 73 74 #ifdef _GLIBCXX_HAVE_LINUX_FUTEX 75 #define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT 76 // returns true if wait ended before timeout 77 template
78 bool 79 __platform_wait_until_impl(const __platform_wait_t* __addr, 80 __platform_wait_t __old, 81 const chrono::time_point<__wait_clock_t, _Dur>& 82 __atime) noexcept 83 { 84 auto __s = chrono::time_point_cast
(__atime); 85 auto __ns = chrono::duration_cast
(__atime - __s); 86 87 struct timespec __rt = 88 { 89 static_cast
(__s.time_since_epoch().count()), 90 static_cast
(__ns.count()) 91 }; 92 93 auto __e = syscall (SYS_futex, __addr, 94 static_cast
(__futex_wait_flags:: 95 __wait_bitset_private), 96 __old, &__rt, nullptr, 97 static_cast
(__futex_wait_flags:: 98 __bitset_match_any)); 99 100 if (__e) 101 { 102 if (errno == ETIMEDOUT) 103 return false; 104 if (errno != EINTR && errno != EAGAIN) 105 __throw_system_error(errno); 106 } 107 return true; 108 } 109 110 // returns true if wait ended before timeout 111 template
112 bool 113 __platform_wait_until(const __platform_wait_t* __addr, __platform_wait_t __old, 114 const chrono::time_point<_Clock, _Dur>& __atime) 115 { 116 if constexpr (is_same_v<__wait_clock_t, _Clock>) 117 { 118 return __platform_wait_until_impl(__addr, __old, __atime); 119 } 120 else 121 { 122 if (!__platform_wait_until_impl(__addr, __old, 123 __to_wait_clock(__atime))) 124 { 125 // We got a timeout when measured against __clock_t but 126 // we need to check against the caller-supplied clock 127 // to tell whether we should return a timeout. 128 if (_Clock::now() < __atime) 129 return true; 130 } 131 return false; 132 } 133 } 134 #else 135 // define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement __platform_wait_until() 136 // if there is a more efficient primitive supported by the platform 137 // (e.g. __ulock_wait())which is better than pthread_cond_clockwait 138 #endif // ! PLATFORM_TIMED_WAIT 139 140 #ifdef _GLIBCXX_HAS_GTHREADS 141 // Returns true if wait ended before timeout. 142 // _Clock must be either steady_clock or system_clock. 143 template
144 bool 145 __cond_wait_until_impl(__condvar& __cv, mutex& __mx, 146 const chrono::time_point<_Clock, _Dur>& __atime) 147 { 148 static_assert(std::__is_one_of<_Clock, chrono::steady_clock, 149 chrono::system_clock>::value); 150 151 auto __s = chrono::time_point_cast
(__atime); 152 auto __ns = chrono::duration_cast
(__atime - __s); 153 154 __gthread_time_t __ts = 155 { 156 static_cast
(__s.time_since_epoch().count()), 157 static_cast
(__ns.count()) 158 }; 159 160 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 161 if constexpr (is_same_v
) 162 __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts); 163 else 164 #endif 165 __cv.wait_until(__mx, __ts); 166 return _Clock::now() < __atime; 167 } 168 169 // returns true if wait ended before timeout 170 template
171 bool 172 __cond_wait_until(__condvar& __cv, mutex& __mx, 173 const chrono::time_point<_Clock, _Dur>& __atime) 174 { 175 #ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 176 if constexpr (is_same_v<_Clock, chrono::steady_clock>) 177 return __detail::__cond_wait_until_impl(__cv, __mx, __atime); 178 else 179 #endif 180 if constexpr (is_same_v<_Clock, chrono::system_clock>) 181 return __detail::__cond_wait_until_impl(__cv, __mx, __atime); 182 else 183 { 184 if (__cond_wait_until_impl(__cv, __mx, 185 __to_wait_clock(__atime))) 186 { 187 // We got a timeout when measured against __clock_t but 188 // we need to check against the caller-supplied clock 189 // to tell whether we should return a timeout. 190 if (_Clock::now() < __atime) 191 return true; 192 } 193 return false; 194 } 195 } 196 #endif // _GLIBCXX_HAS_GTHREADS 197 198 struct __timed_waiter_pool : __waiter_pool_base 199 { 200 // returns true if wait ended before timeout 201 template
202 bool 203 _M_do_wait_until(__platform_wait_t* __addr, __platform_wait_t __old, 204 const chrono::time_point<_Clock, _Dur>& __atime) 205 { 206 #ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT 207 return __platform_wait_until(__addr, __old, __atime); 208 #else 209 __platform_wait_t __val; 210 __atomic_load(__addr, &__val, __ATOMIC_RELAXED); 211 if (__val == __old) 212 { 213 lock_guard
__l(_M_mtx); 214 return __cond_wait_until(_M_cv, _M_mtx, __atime); 215 } 216 else 217 return true; 218 #endif // _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT 219 } 220 }; 221 222 struct __timed_backoff_spin_policy 223 { 224 __wait_clock_t::time_point _M_deadline; 225 __wait_clock_t::time_point _M_t0; 226 227 template
228 __timed_backoff_spin_policy(chrono::time_point<_Clock, _Dur> 229 __deadline = _Clock::time_point::max(), 230 chrono::time_point<_Clock, _Dur> 231 __t0 = _Clock::now()) noexcept 232 : _M_deadline(__to_wait_clock(__deadline)) 233 , _M_t0(__to_wait_clock(__t0)) 234 { } 235 236 bool 237 operator()() const noexcept 238 { 239 using namespace literals::chrono_literals; 240 auto __now = __wait_clock_t::now(); 241 if (_M_deadline <= __now) 242 return false; 243 244 // FIXME: this_thread::sleep_for not available #ifdef _GLIBCXX_NO_SLEEP 245 246 auto __elapsed = __now - _M_t0; 247 if (__elapsed > 128ms) 248 { 249 this_thread::sleep_for(64ms); 250 } 251 else if (__elapsed > 64us) 252 { 253 this_thread::sleep_for(__elapsed / 2); 254 } 255 else if (__elapsed > 4us) 256 { 257 __thread_yield(); 258 } 259 else 260 return false; 261 return true; 262 } 263 }; 264 265 template
266 struct __timed_waiter : __waiter_base<__timed_waiter_pool> 267 { 268 using __base_type = __waiter_base<__timed_waiter_pool>; 269 270 template
271 __timed_waiter(const _Tp* __addr) noexcept 272 : __base_type(__addr) 273 { 274 if constexpr (_EntersWait::value) 275 _M_w._M_enter_wait(); 276 } 277 278 ~__timed_waiter() 279 { 280 if constexpr (_EntersWait::value) 281 _M_w._M_leave_wait(); 282 } 283 284 // returns true if wait ended before timeout 285 template
287 bool 288 _M_do_wait_until_v(_Tp __old, _ValFn __vfn, 289 const chrono::time_point<_Clock, _Dur>& 290 __atime) noexcept 291 { 292 __platform_wait_t __val; 293 if (_M_do_spin(__old, std::move(__vfn), __val, 294 __timed_backoff_spin_policy(__atime))) 295 return true; 296 return __base_type::_M_w._M_do_wait_until(__base_type::_M_addr, __val, __atime); 297 } 298 299 // returns true if wait ended before timeout 300 template
302 bool 303 _M_do_wait_until(_Pred __pred, __platform_wait_t __val, 304 const chrono::time_point<_Clock, _Dur>& 305 __atime) noexcept 306 { 307 for (auto __now = _Clock::now(); __now < __atime; 308 __now = _Clock::now()) 309 { 310 if (__base_type::_M_w._M_do_wait_until( 311 __base_type::_M_addr, __val, __atime) 312 && __pred()) 313 return true; 314 315 if (__base_type::_M_do_spin(__pred, __val, 316 __timed_backoff_spin_policy(__atime, __now))) 317 return true; 318 } 319 return false; 320 } 321 322 // returns true if wait ended before timeout 323 template
325 bool 326 _M_do_wait_until(_Pred __pred, 327 const chrono::time_point<_Clock, _Dur>& 328 __atime) noexcept 329 { 330 __platform_wait_t __val; 331 if (__base_type::_M_do_spin(__pred, __val, 332 __timed_backoff_spin_policy(__atime))) 333 return true; 334 return _M_do_wait_until(__pred, __val, __atime); 335 } 336 337 template
339 bool 340 _M_do_wait_for_v(_Tp __old, _ValFn __vfn, 341 const chrono::duration<_Rep, _Period>& 342 __rtime) noexcept 343 { 344 __platform_wait_t __val; 345 if (_M_do_spin_v(__old, std::move(__vfn), __val)) 346 return true; 347 348 if (!__rtime.count()) 349 return false; // no rtime supplied, and spin did not acquire 350 351 auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime); 352 353 return __base_type::_M_w._M_do_wait_until( 354 __base_type::_M_addr, 355 __val, 356 chrono::steady_clock::now() + __reltime); 357 } 358 359 template
361 bool 362 _M_do_wait_for(_Pred __pred, 363 const chrono::duration<_Rep, _Period>& __rtime) noexcept 364 { 365 __platform_wait_t __val; 366 if (__base_type::_M_do_spin(__pred, __val)) 367 return true; 368 369 if (!__rtime.count()) 370 return false; // no rtime supplied, and spin did not acquire 371 372 auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime); 373 374 return _M_do_wait_until(__pred, __val, 375 chrono::steady_clock::now() + __reltime); 376 } 377 }; 378 379 using __enters_timed_wait = __timed_waiter
; 380 using __bare_timed_wait = __timed_waiter
; 381 } // namespace __detail 382 383 // returns true if wait ended before timeout 384 template
386 bool 387 __atomic_wait_address_until_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn, 388 const chrono::time_point<_Clock, _Dur>& 389 __atime) noexcept 390 { 391 __detail::__enters_timed_wait __w{__addr}; 392 return __w._M_do_wait_until_v(__old, __vfn, __atime); 393 } 394 395 template
397 bool 398 __atomic_wait_address_until(const _Tp* __addr, _Pred __pred, 399 const chrono::time_point<_Clock, _Dur>& 400 __atime) noexcept 401 { 402 __detail::__enters_timed_wait __w{__addr}; 403 return __w._M_do_wait_until(__pred, __atime); 404 } 405 406 template
408 bool 409 __atomic_wait_address_until_bare(const __detail::__platform_wait_t* __addr, 410 _Pred __pred, 411 const chrono::time_point<_Clock, _Dur>& 412 __atime) noexcept 413 { 414 __detail::__bare_timed_wait __w{__addr}; 415 return __w._M_do_wait_until(__pred, __atime); 416 } 417 418 template
420 bool 421 __atomic_wait_address_for_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn, 422 const chrono::duration<_Rep, _Period>& __rtime) noexcept 423 { 424 __detail::__enters_timed_wait __w{__addr}; 425 return __w._M_do_wait_for_v(__old, __vfn, __rtime); 426 } 427 428 template
430 bool 431 __atomic_wait_address_for(const _Tp* __addr, _Pred __pred, 432 const chrono::duration<_Rep, _Period>& __rtime) noexcept 433 { 434 435 __detail::__enters_timed_wait __w{__addr}; 436 return __w._M_do_wait_for(__pred, __rtime); 437 } 438 439 template
441 bool 442 __atomic_wait_address_for_bare(const __detail::__platform_wait_t* __addr, 443 _Pred __pred, 444 const chrono::duration<_Rep, _Period>& __rtime) noexcept 445 { 446 __detail::__bare_timed_wait __w{__addr}; 447 return __w._M_do_wait_for(__pred, __rtime); 448 } 449 _GLIBCXX_END_NAMESPACE_VERSION 450 } // namespace std 451 #endif // __cpp_lib_atomic_wait 452 #endif // _GLIBCXX_ATOMIC_TIMED_WAIT_H
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™