14fee23f9Smrg// <condition_variable> -*- C++ -*- 24fee23f9Smrg 3b1e83836Smrg// Copyright (C) 2008-2022 Free Software Foundation, Inc. 44fee23f9Smrg// 54fee23f9Smrg// This file is part of the GNU ISO C++ Library. This library is free 64fee23f9Smrg// software; you can redistribute it and/or modify it under the 74fee23f9Smrg// terms of the GNU General Public License as published by the 84fee23f9Smrg// Free Software Foundation; either version 3, or (at your option) 94fee23f9Smrg// any later version. 104fee23f9Smrg 114fee23f9Smrg// This library is distributed in the hope that it will be useful, 124fee23f9Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 134fee23f9Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144fee23f9Smrg// GNU General Public License for more details. 154fee23f9Smrg 164fee23f9Smrg// Under Section 7 of GPL version 3, you are granted additional 174fee23f9Smrg// permissions described in the GCC Runtime Library Exception, version 184fee23f9Smrg// 3.1, as published by the Free Software Foundation. 194fee23f9Smrg 204fee23f9Smrg// You should have received a copy of the GNU General Public License and 214fee23f9Smrg// a copy of the GCC Runtime Library Exception along with this program; 224fee23f9Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 234fee23f9Smrg// <http://www.gnu.org/licenses/>. 244fee23f9Smrg 2548fb7bfaSmrg/** @file include/condition_variable 264fee23f9Smrg * This is a Standard C++ Library header. 274fee23f9Smrg */ 284fee23f9Smrg 294fee23f9Smrg#ifndef _GLIBCXX_CONDITION_VARIABLE 304fee23f9Smrg#define _GLIBCXX_CONDITION_VARIABLE 1 314fee23f9Smrg 324fee23f9Smrg#pragma GCC system_header 334fee23f9Smrg 3448fb7bfaSmrg#if __cplusplus < 201103L 354fee23f9Smrg# include <bits/c++0x_warning.h> 364fee23f9Smrg#else 374fee23f9Smrg 38b1e83836Smrg#include <bits/chrono.h> 39f9a78e0eSmrg#include <bits/std_mutex.h> 40181254a7Smrg#include <bits/unique_lock.h> 414d5abbe8Smrg#include <bits/alloc_traits.h> 424d5abbe8Smrg#include <bits/shared_ptr.h> 43f9a78e0eSmrg#include <bits/cxxabi_forced.h> 444fee23f9Smrg 45fb8a8121Smrg#if __cplusplus > 201703L 46fb8a8121Smrg# include <stop_token> 47fb8a8121Smrg#endif 48fb8a8121Smrg 49181254a7Smrg#if defined(_GLIBCXX_HAS_GTHREADS) 504fee23f9Smrg 5148fb7bfaSmrgnamespace std _GLIBCXX_VISIBILITY(default) 524fee23f9Smrg{ 5348fb7bfaSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 5448fb7bfaSmrg 554fee23f9Smrg /** 564fee23f9Smrg * @defgroup condition_variables Condition Variables 574fee23f9Smrg * @ingroup concurrency 584fee23f9Smrg * 594fee23f9Smrg * Classes for condition_variable support. 604fee23f9Smrg * @{ 614fee23f9Smrg */ 624fee23f9Smrg 634fee23f9Smrg /// cv_status 644fee23f9Smrg enum class cv_status { no_timeout, timeout }; 654fee23f9Smrg 664fee23f9Smrg /// condition_variable 674fee23f9Smrg class condition_variable 684fee23f9Smrg { 69fb8a8121Smrg using steady_clock = chrono::steady_clock; 70fb8a8121Smrg using system_clock = chrono::system_clock; 71fb8a8121Smrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 72fb8a8121Smrg using __clock_t = steady_clock; 73fb8a8121Smrg#else 74fb8a8121Smrg using __clock_t = system_clock; 75fb8a8121Smrg#endif 7648fb7bfaSmrg 77b1e83836Smrg __condvar _M_cond; 784fee23f9Smrg 794fee23f9Smrg public: 80b1e83836Smrg typedef __gthread_cond_t* native_handle_type; 814fee23f9Smrg 8248fb7bfaSmrg condition_variable() noexcept; 8348fb7bfaSmrg ~condition_variable() noexcept; 844fee23f9Smrg 854fee23f9Smrg condition_variable(const condition_variable&) = delete; 864fee23f9Smrg condition_variable& operator=(const condition_variable&) = delete; 874fee23f9Smrg 884fee23f9Smrg void 8948fb7bfaSmrg notify_one() noexcept; 904fee23f9Smrg 914fee23f9Smrg void 9248fb7bfaSmrg notify_all() noexcept; 934fee23f9Smrg 944fee23f9Smrg void 95b1e83836Smrg wait(unique_lock<mutex>& __lock); 964fee23f9Smrg 974fee23f9Smrg template<typename _Predicate> 984fee23f9Smrg void 994fee23f9Smrg wait(unique_lock<mutex>& __lock, _Predicate __p) 1004fee23f9Smrg { 1014fee23f9Smrg while (!__p()) 1024fee23f9Smrg wait(__lock); 1034fee23f9Smrg } 1044fee23f9Smrg 105fb8a8121Smrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 1064fee23f9Smrg template<typename _Duration> 1074fee23f9Smrg cv_status 1084fee23f9Smrg wait_until(unique_lock<mutex>& __lock, 109fb8a8121Smrg const chrono::time_point<steady_clock, _Duration>& __atime) 110fb8a8121Smrg { return __wait_until_impl(__lock, __atime); } 111fb8a8121Smrg#endif 112fb8a8121Smrg 113fb8a8121Smrg template<typename _Duration> 114fb8a8121Smrg cv_status 115fb8a8121Smrg wait_until(unique_lock<mutex>& __lock, 116fb8a8121Smrg const chrono::time_point<system_clock, _Duration>& __atime) 1174fee23f9Smrg { return __wait_until_impl(__lock, __atime); } 1184fee23f9Smrg 1194fee23f9Smrg template<typename _Clock, typename _Duration> 1204fee23f9Smrg cv_status 1214fee23f9Smrg wait_until(unique_lock<mutex>& __lock, 1224fee23f9Smrg const chrono::time_point<_Clock, _Duration>& __atime) 1234fee23f9Smrg { 124fb8a8121Smrg#if __cplusplus > 201703L 125fb8a8121Smrg static_assert(chrono::is_clock_v<_Clock>); 126fb8a8121Smrg#endif 127b1e83836Smrg using __s_dur = typename __clock_t::duration; 1284fee23f9Smrg const typename _Clock::time_point __c_entry = _Clock::now(); 1294fee23f9Smrg const __clock_t::time_point __s_entry = __clock_t::now(); 13048fb7bfaSmrg const auto __delta = __atime - __c_entry; 131b1e83836Smrg const auto __s_atime = __s_entry + 132b1e83836Smrg chrono::__detail::ceil<__s_dur>(__delta); 1334fee23f9Smrg 134181254a7Smrg if (__wait_until_impl(__lock, __s_atime) == cv_status::no_timeout) 135181254a7Smrg return cv_status::no_timeout; 136181254a7Smrg // We got a timeout when measured against __clock_t but 137181254a7Smrg // we need to check against the caller-supplied clock 138181254a7Smrg // to tell whether we should return a timeout. 139181254a7Smrg if (_Clock::now() < __atime) 140181254a7Smrg return cv_status::no_timeout; 141181254a7Smrg return cv_status::timeout; 1424fee23f9Smrg } 1434fee23f9Smrg 1444fee23f9Smrg template<typename _Clock, typename _Duration, typename _Predicate> 1454fee23f9Smrg bool 1464fee23f9Smrg wait_until(unique_lock<mutex>& __lock, 1474fee23f9Smrg const chrono::time_point<_Clock, _Duration>& __atime, 1484fee23f9Smrg _Predicate __p) 1494fee23f9Smrg { 1504fee23f9Smrg while (!__p()) 1514fee23f9Smrg if (wait_until(__lock, __atime) == cv_status::timeout) 1524fee23f9Smrg return __p(); 1534fee23f9Smrg return true; 1544fee23f9Smrg } 1554fee23f9Smrg 1564fee23f9Smrg template<typename _Rep, typename _Period> 1574fee23f9Smrg cv_status 1584fee23f9Smrg wait_for(unique_lock<mutex>& __lock, 1594fee23f9Smrg const chrono::duration<_Rep, _Period>& __rtime) 160d79abf08Smrg { 161fb8a8121Smrg using __dur = typename steady_clock::duration; 162b1e83836Smrg return wait_until(__lock, 163b1e83836Smrg steady_clock::now() + 164b1e83836Smrg chrono::__detail::ceil<__dur>(__rtime)); 165d79abf08Smrg } 1664fee23f9Smrg 1674fee23f9Smrg template<typename _Rep, typename _Period, typename _Predicate> 1684fee23f9Smrg bool 1694fee23f9Smrg wait_for(unique_lock<mutex>& __lock, 1704fee23f9Smrg const chrono::duration<_Rep, _Period>& __rtime, 1714fee23f9Smrg _Predicate __p) 172d79abf08Smrg { 173fb8a8121Smrg using __dur = typename steady_clock::duration; 174b1e83836Smrg return wait_until(__lock, 175b1e83836Smrg steady_clock::now() + 176b1e83836Smrg chrono::__detail::ceil<__dur>(__rtime), 177181254a7Smrg std::move(__p)); 178d79abf08Smrg } 1794fee23f9Smrg 1804fee23f9Smrg native_handle_type 1814fee23f9Smrg native_handle() 182b1e83836Smrg { return _M_cond.native_handle(); } 1834fee23f9Smrg 1844fee23f9Smrg private: 185fb8a8121Smrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 18648fb7bfaSmrg template<typename _Dur> 1874fee23f9Smrg cv_status 1884fee23f9Smrg __wait_until_impl(unique_lock<mutex>& __lock, 189fb8a8121Smrg const chrono::time_point<steady_clock, _Dur>& __atime) 190fb8a8121Smrg { 191fb8a8121Smrg auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 192fb8a8121Smrg auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 193fb8a8121Smrg 194fb8a8121Smrg __gthread_time_t __ts = 195fb8a8121Smrg { 196fb8a8121Smrg static_cast<std::time_t>(__s.time_since_epoch().count()), 197fb8a8121Smrg static_cast<long>(__ns.count()) 198fb8a8121Smrg }; 199fb8a8121Smrg 200b1e83836Smrg _M_cond.wait_until(*__lock.mutex(), CLOCK_MONOTONIC, __ts); 201fb8a8121Smrg 202fb8a8121Smrg return (steady_clock::now() < __atime 203fb8a8121Smrg ? cv_status::no_timeout : cv_status::timeout); 204fb8a8121Smrg } 205fb8a8121Smrg#endif 206fb8a8121Smrg 207fb8a8121Smrg template<typename _Dur> 208fb8a8121Smrg cv_status 209fb8a8121Smrg __wait_until_impl(unique_lock<mutex>& __lock, 210fb8a8121Smrg const chrono::time_point<system_clock, _Dur>& __atime) 2114fee23f9Smrg { 21248fb7bfaSmrg auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 21348fb7bfaSmrg auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 2144fee23f9Smrg 2154fee23f9Smrg __gthread_time_t __ts = 2164fee23f9Smrg { 2174fee23f9Smrg static_cast<std::time_t>(__s.time_since_epoch().count()), 2184fee23f9Smrg static_cast<long>(__ns.count()) 2194fee23f9Smrg }; 2204fee23f9Smrg 221b1e83836Smrg _M_cond.wait_until(*__lock.mutex(), __ts); 2224fee23f9Smrg 223fb8a8121Smrg return (system_clock::now() < __atime 2244fee23f9Smrg ? cv_status::no_timeout : cv_status::timeout); 2254fee23f9Smrg } 2264fee23f9Smrg }; 2274fee23f9Smrg 2284d5abbe8Smrg void 2294d5abbe8Smrg notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); 2304d5abbe8Smrg 2314d5abbe8Smrg struct __at_thread_exit_elt 2324d5abbe8Smrg { 2334d5abbe8Smrg __at_thread_exit_elt* _M_next; 2344d5abbe8Smrg void (*_M_cb)(void*); 2354d5abbe8Smrg }; 2364d5abbe8Smrg 237*0a307195Smrg_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) 2384d5abbe8Smrg 2394fee23f9Smrg /// condition_variable_any 2404fee23f9Smrg // Like above, but mutex is not required to have try_lock. 2414fee23f9Smrg class condition_variable_any 2424fee23f9Smrg { 243fb8a8121Smrg#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT 244fb8a8121Smrg using __clock_t = chrono::steady_clock; 245fb8a8121Smrg#else 246fb8a8121Smrg using __clock_t = chrono::system_clock; 247fb8a8121Smrg#endif 2484fee23f9Smrg condition_variable _M_cond; 2494d5abbe8Smrg shared_ptr<mutex> _M_mutex; 2504fee23f9Smrg 25148fb7bfaSmrg // scoped unlock - unlocks in ctor, re-locks in dtor 25248fb7bfaSmrg template<typename _Lock> 25348fb7bfaSmrg struct _Unlock 25448fb7bfaSmrg { 25548fb7bfaSmrg explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); } 2564fee23f9Smrg 257fb8a8121Smrg#pragma GCC diagnostic push 258fb8a8121Smrg#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 25948fb7bfaSmrg ~_Unlock() noexcept(false) 26048fb7bfaSmrg { 26148fb7bfaSmrg if (uncaught_exception()) 2624d5abbe8Smrg { 2634d5abbe8Smrg __try 2644d5abbe8Smrg { _M_lock.lock(); } 2654d5abbe8Smrg __catch(const __cxxabiv1::__forced_unwind&) 2664d5abbe8Smrg { __throw_exception_again; } 2674d5abbe8Smrg __catch(...) 2684d5abbe8Smrg { } 2694d5abbe8Smrg } 27048fb7bfaSmrg else 27148fb7bfaSmrg _M_lock.lock(); 27248fb7bfaSmrg } 273fb8a8121Smrg#pragma GCC diagnostic pop 27448fb7bfaSmrg 27548fb7bfaSmrg _Unlock(const _Unlock&) = delete; 27648fb7bfaSmrg _Unlock& operator=(const _Unlock&) = delete; 27748fb7bfaSmrg 27848fb7bfaSmrg _Lock& _M_lock; 27948fb7bfaSmrg }; 28048fb7bfaSmrg 28148fb7bfaSmrg public: 2824d5abbe8Smrg condition_variable_any() : _M_mutex(std::make_shared<mutex>()) { } 2834d5abbe8Smrg ~condition_variable_any() = default; 2844fee23f9Smrg 2854fee23f9Smrg condition_variable_any(const condition_variable_any&) = delete; 2864fee23f9Smrg condition_variable_any& operator=(const condition_variable_any&) = delete; 2874fee23f9Smrg 2884fee23f9Smrg void 28948fb7bfaSmrg notify_one() noexcept 2904fee23f9Smrg { 2914d5abbe8Smrg lock_guard<mutex> __lock(*_M_mutex); 2924fee23f9Smrg _M_cond.notify_one(); 2934fee23f9Smrg } 2944fee23f9Smrg 2954fee23f9Smrg void 29648fb7bfaSmrg notify_all() noexcept 2974fee23f9Smrg { 2984d5abbe8Smrg lock_guard<mutex> __lock(*_M_mutex); 2994fee23f9Smrg _M_cond.notify_all(); 3004fee23f9Smrg } 3014fee23f9Smrg 3024fee23f9Smrg template<typename _Lock> 3034fee23f9Smrg void 3044fee23f9Smrg wait(_Lock& __lock) 3054fee23f9Smrg { 3064d5abbe8Smrg shared_ptr<mutex> __mutex = _M_mutex; 3074d5abbe8Smrg unique_lock<mutex> __my_lock(*__mutex); 30848fb7bfaSmrg _Unlock<_Lock> __unlock(__lock); 3094d5abbe8Smrg // *__mutex must be unlocked before re-locking __lock so move 3104d5abbe8Smrg // ownership of *__mutex lock to an object with shorter lifetime. 31148fb7bfaSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 31248fb7bfaSmrg _M_cond.wait(__my_lock2); 3134fee23f9Smrg } 3144fee23f9Smrg 3154fee23f9Smrg 3164fee23f9Smrg template<typename _Lock, typename _Predicate> 3174fee23f9Smrg void 3184fee23f9Smrg wait(_Lock& __lock, _Predicate __p) 3194fee23f9Smrg { 3204fee23f9Smrg while (!__p()) 3214fee23f9Smrg wait(__lock); 3224fee23f9Smrg } 3234fee23f9Smrg 3244fee23f9Smrg template<typename _Lock, typename _Clock, typename _Duration> 3254fee23f9Smrg cv_status 3264fee23f9Smrg wait_until(_Lock& __lock, 3274fee23f9Smrg const chrono::time_point<_Clock, _Duration>& __atime) 3284fee23f9Smrg { 3294d5abbe8Smrg shared_ptr<mutex> __mutex = _M_mutex; 3304d5abbe8Smrg unique_lock<mutex> __my_lock(*__mutex); 33148fb7bfaSmrg _Unlock<_Lock> __unlock(__lock); 3324d5abbe8Smrg // *__mutex must be unlocked before re-locking __lock so move 3334d5abbe8Smrg // ownership of *__mutex lock to an object with shorter lifetime. 33448fb7bfaSmrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 33548fb7bfaSmrg return _M_cond.wait_until(__my_lock2, __atime); 3364fee23f9Smrg } 3374fee23f9Smrg 3384fee23f9Smrg template<typename _Lock, typename _Clock, 3394fee23f9Smrg typename _Duration, typename _Predicate> 3404fee23f9Smrg bool 3414fee23f9Smrg wait_until(_Lock& __lock, 3424fee23f9Smrg const chrono::time_point<_Clock, _Duration>& __atime, 3434fee23f9Smrg _Predicate __p) 3444fee23f9Smrg { 3454fee23f9Smrg while (!__p()) 3464fee23f9Smrg if (wait_until(__lock, __atime) == cv_status::timeout) 3474fee23f9Smrg return __p(); 3484fee23f9Smrg return true; 3494fee23f9Smrg } 3504fee23f9Smrg 3514fee23f9Smrg template<typename _Lock, typename _Rep, typename _Period> 3524fee23f9Smrg cv_status 3534fee23f9Smrg wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime) 3544fee23f9Smrg { return wait_until(__lock, __clock_t::now() + __rtime); } 3554fee23f9Smrg 3564fee23f9Smrg template<typename _Lock, typename _Rep, 3574fee23f9Smrg typename _Period, typename _Predicate> 3584fee23f9Smrg bool 3594fee23f9Smrg wait_for(_Lock& __lock, 3604fee23f9Smrg const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) 3614fee23f9Smrg { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } 362fb8a8121Smrg 363fb8a8121Smrg#ifdef __cpp_lib_jthread 364fb8a8121Smrg template <class _Lock, class _Predicate> 365fb8a8121Smrg bool wait(_Lock& __lock, 366fb8a8121Smrg stop_token __stoken, 367fb8a8121Smrg _Predicate __p) 368fb8a8121Smrg { 369fb8a8121Smrg if (__stoken.stop_requested()) 370fb8a8121Smrg { 371fb8a8121Smrg return __p(); 372fb8a8121Smrg } 373fb8a8121Smrg 374fb8a8121Smrg std::stop_callback __cb(__stoken, [this] { notify_all(); }); 375fb8a8121Smrg shared_ptr<mutex> __mutex = _M_mutex; 376fb8a8121Smrg while (!__p()) 377fb8a8121Smrg { 378fb8a8121Smrg unique_lock<mutex> __my_lock(*__mutex); 379fb8a8121Smrg if (__stoken.stop_requested()) 380fb8a8121Smrg { 381fb8a8121Smrg return false; 382fb8a8121Smrg } 383fb8a8121Smrg // *__mutex must be unlocked before re-locking __lock so move 384fb8a8121Smrg // ownership of *__mutex lock to an object with shorter lifetime. 385fb8a8121Smrg _Unlock<_Lock> __unlock(__lock); 386fb8a8121Smrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 387fb8a8121Smrg _M_cond.wait(__my_lock2); 388fb8a8121Smrg } 389fb8a8121Smrg return true; 390fb8a8121Smrg } 391fb8a8121Smrg 392fb8a8121Smrg template <class _Lock, class _Clock, class _Duration, class _Predicate> 393fb8a8121Smrg bool wait_until(_Lock& __lock, 394fb8a8121Smrg stop_token __stoken, 395fb8a8121Smrg const chrono::time_point<_Clock, _Duration>& __abs_time, 396fb8a8121Smrg _Predicate __p) 397fb8a8121Smrg { 398fb8a8121Smrg if (__stoken.stop_requested()) 399fb8a8121Smrg { 400fb8a8121Smrg return __p(); 401fb8a8121Smrg } 402fb8a8121Smrg 403fb8a8121Smrg std::stop_callback __cb(__stoken, [this] { notify_all(); }); 404fb8a8121Smrg shared_ptr<mutex> __mutex = _M_mutex; 405fb8a8121Smrg while (!__p()) 406fb8a8121Smrg { 407fb8a8121Smrg bool __stop; 408fb8a8121Smrg { 409fb8a8121Smrg unique_lock<mutex> __my_lock(*__mutex); 410fb8a8121Smrg if (__stoken.stop_requested()) 411fb8a8121Smrg { 412fb8a8121Smrg return false; 413fb8a8121Smrg } 414fb8a8121Smrg _Unlock<_Lock> __u(__lock); 415fb8a8121Smrg unique_lock<mutex> __my_lock2(std::move(__my_lock)); 416fb8a8121Smrg const auto __status = _M_cond.wait_until(__my_lock2, __abs_time); 417fb8a8121Smrg __stop = (__status == std::cv_status::timeout) || __stoken.stop_requested(); 418fb8a8121Smrg } 419fb8a8121Smrg if (__stop) 420fb8a8121Smrg { 421fb8a8121Smrg return __p(); 422fb8a8121Smrg } 423fb8a8121Smrg } 424fb8a8121Smrg return true; 425fb8a8121Smrg } 426fb8a8121Smrg 427fb8a8121Smrg template <class _Lock, class _Rep, class _Period, class _Predicate> 428fb8a8121Smrg bool wait_for(_Lock& __lock, 429fb8a8121Smrg stop_token __stoken, 430fb8a8121Smrg const chrono::duration<_Rep, _Period>& __rel_time, 431fb8a8121Smrg _Predicate __p) 432fb8a8121Smrg { 433fb8a8121Smrg auto __abst = std::chrono::steady_clock::now() + __rel_time; 434fb8a8121Smrg return wait_until(__lock, 435fb8a8121Smrg std::move(__stoken), 436fb8a8121Smrg __abst, 437fb8a8121Smrg std::move(__p)); 438fb8a8121Smrg } 439fb8a8121Smrg#endif 4404fee23f9Smrg }; 4414fee23f9Smrg 442*0a307195Smrg_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) 4434d5abbe8Smrg 444a448f87cSmrg /// @} group condition_variables 44548fb7bfaSmrg_GLIBCXX_END_NAMESPACE_VERSION 44648fb7bfaSmrg} // namespace 4474fee23f9Smrg 448181254a7Smrg#endif // _GLIBCXX_HAS_GTHREADS 44948fb7bfaSmrg#endif // C++11 4504fee23f9Smrg#endif // _GLIBCXX_CONDITION_VARIABLE 451