1*38fd1498Szrj// <condition_variable> -*- C++ -*- 2*38fd1498Szrj 3*38fd1498Szrj// Copyright (C) 2008-2018 Free Software Foundation, Inc. 4*38fd1498Szrj// 5*38fd1498Szrj// This file is part of the GNU ISO C++ Library. This library is free 6*38fd1498Szrj// software; you can redistribute it and/or modify it under the 7*38fd1498Szrj// terms of the GNU General Public License as published by the 8*38fd1498Szrj// Free Software Foundation; either version 3, or (at your option) 9*38fd1498Szrj// any later version. 10*38fd1498Szrj 11*38fd1498Szrj// This library is distributed in the hope that it will be useful, 12*38fd1498Szrj// but WITHOUT ANY WARRANTY; without even the implied warranty of 13*38fd1498Szrj// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*38fd1498Szrj// GNU General Public License for more details. 15*38fd1498Szrj 16*38fd1498Szrj// Under Section 7 of GPL version 3, you are granted additional 17*38fd1498Szrj// permissions described in the GCC Runtime Library Exception, version 18*38fd1498Szrj// 3.1, as published by the Free Software Foundation. 19*38fd1498Szrj 20*38fd1498Szrj// You should have received a copy of the GNU General Public License and 21*38fd1498Szrj// a copy of the GCC Runtime Library Exception along with this program; 22*38fd1498Szrj// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23*38fd1498Szrj// <http://www.gnu.org/licenses/>. 24*38fd1498Szrj 25*38fd1498Szrj/** @file include/condition_variable 26*38fd1498Szrj * This is a Standard C++ Library header. 27*38fd1498Szrj */ 28*38fd1498Szrj 29*38fd1498Szrj#ifndef _GLIBCXX_CONDITION_VARIABLE 30*38fd1498Szrj#define _GLIBCXX_CONDITION_VARIABLE 1 31*38fd1498Szrj 32*38fd1498Szrj#pragma GCC system_header 33*38fd1498Szrj 34*38fd1498Szrj#if __cplusplus < 201103L 35*38fd1498Szrj# include <bits/c++0x_warning.h> 36*38fd1498Szrj#else 37*38fd1498Szrj 38*38fd1498Szrj#include <chrono> 39*38fd1498Szrj#include <bits/std_mutex.h> 40*38fd1498Szrj#include <ext/concurrence.h> 41*38fd1498Szrj#include <bits/alloc_traits.h> 42*38fd1498Szrj#include <bits/allocator.h> 43*38fd1498Szrj#include <bits/unique_ptr.h> 44*38fd1498Szrj#include <bits/shared_ptr.h> 45*38fd1498Szrj#include <bits/cxxabi_forced.h> 46*38fd1498Szrj 47*38fd1498Szrj#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 48*38fd1498Szrj 49*38fd1498Szrjnamespace std _GLIBCXX_VISIBILITY(default) 50*38fd1498Szrj{ 51*38fd1498Szrj_GLIBCXX_BEGIN_NAMESPACE_VERSION 52*38fd1498Szrj 53*38fd1498Szrj /** 54*38fd1498Szrj * @defgroup condition_variables Condition Variables 55*38fd1498Szrj * @ingroup concurrency 56*38fd1498Szrj * 57*38fd1498Szrj * Classes for condition_variable support. 58*38fd1498Szrj * @{ 59*38fd1498Szrj */ 60*38fd1498Szrj 61*38fd1498Szrj /// cv_status 62*38fd1498Szrj enum class cv_status { no_timeout, timeout }; 63*38fd1498Szrj 64*38fd1498Szrj /// condition_variable 65*38fd1498Szrj class condition_variable 66*38fd1498Szrj { 67*38fd1498Szrj typedef chrono::system_clock __clock_t; 68*38fd1498Szrj typedef __gthread_cond_t __native_type; 69*38fd1498Szrj 70*38fd1498Szrj#ifdef __GTHREAD_COND_INIT 71*38fd1498Szrj __native_type _M_cond = __GTHREAD_COND_INIT; 72*38fd1498Szrj#else 73*38fd1498Szrj __native_type _M_cond; 74*38fd1498Szrj#endif 75*38fd1498Szrj 76*38fd1498Szrj public: 77*38fd1498Szrj typedef __native_type* native_handle_type; 78*38fd1498Szrj 79*38fd1498Szrj condition_variable() noexcept; 80*38fd1498Szrj ~condition_variable() noexcept; 81*38fd1498Szrj 82*38fd1498Szrj condition_variable(const condition_variable&) = delete; 83*38fd1498Szrj condition_variable& operator=(const condition_variable&) = delete; 84*38fd1498Szrj 85*38fd1498Szrj void 86*38fd1498Szrj notify_one() noexcept; 87*38fd1498Szrj 88*38fd1498Szrj void 89*38fd1498Szrj notify_all() noexcept; 90*38fd1498Szrj 91*38fd1498Szrj void 92*38fd1498Szrj wait(unique_lock<mutex>& __lock) noexcept; 93*38fd1498Szrj 94*38fd1498Szrj template<typename _Predicate> 95*38fd1498Szrj void 96*38fd1498Szrj wait(unique_lock<mutex>& __lock, _Predicate __p) 97*38fd1498Szrj { 98*38fd1498Szrj while (!__p()) 99*38fd1498Szrj wait(__lock); 100*38fd1498Szrj } 101*38fd1498Szrj 102*38fd1498Szrj template<typename _Duration> 103*38fd1498Szrj cv_status 104*38fd1498Szrj wait_until(unique_lock<mutex>& __lock, 105*38fd1498Szrj const chrono::time_point<__clock_t, _Duration>& __atime) 106*38fd1498Szrj { return __wait_until_impl(__lock, __atime); } 107*38fd1498Szrj 108*38fd1498Szrj template<typename _Clock, typename _Duration> 109*38fd1498Szrj cv_status 110*38fd1498Szrj wait_until(unique_lock<mutex>& __lock, 111*38fd1498Szrj const chrono::time_point<_Clock, _Duration>& __atime) 112*38fd1498Szrj { 113*38fd1498Szrj // DR 887 - Sync unknown clock to known clock. 114*38fd1498Szrj const typename _Clock::time_point __c_entry = _Clock::now(); 115*38fd1498Szrj const __clock_t::time_point __s_entry = __clock_t::now(); 116*38fd1498Szrj const auto __delta = __atime - __c_entry; 117*38fd1498Szrj const auto __s_atime = __s_entry + __delta; 118*38fd1498Szrj 119*38fd1498Szrj return __wait_until_impl(__lock, __s_atime); 120*38fd1498Szrj } 121*38fd1498Szrj 122*38fd1498Szrj template<typename _Clock, typename _Duration, typename _Predicate> 123*38fd1498Szrj bool 124*38fd1498Szrj wait_until(unique_lock<mutex>& __lock, 125*38fd1498Szrj const chrono::time_point<_Clock, _Duration>& __atime, 126*38fd1498Szrj _Predicate __p) 127*38fd1498Szrj { 128*38fd1498Szrj while (!__p()) 129*38fd1498Szrj if (wait_until(__lock, __atime) == cv_status::timeout) 130*38fd1498Szrj return __p(); 131*38fd1498Szrj return true; 132*38fd1498Szrj } 133*38fd1498Szrj 134*38fd1498Szrj template<typename _Rep, typename _Period> 135*38fd1498Szrj cv_status 136*38fd1498Szrj wait_for(unique_lock<mutex>& __lock, 137*38fd1498Szrj const chrono::duration<_Rep, _Period>& __rtime) 138*38fd1498Szrj { 139*38fd1498Szrj using __dur = typename __clock_t::duration; 140*38fd1498Szrj auto __reltime = chrono::duration_cast<__dur>(__rtime); 141*38fd1498Szrj if (__reltime < __rtime) 142*38fd1498Szrj ++__reltime; 143*38fd1498Szrj return wait_until(__lock, __clock_t::now() + __reltime); 144*38fd1498Szrj } 145*38fd1498Szrj 146*38fd1498Szrj template<typename _Rep, typename _Period, typename _Predicate> 147*38fd1498Szrj bool 148*38fd1498Szrj wait_for(unique_lock<mutex>& __lock, 149*38fd1498Szrj const chrono::duration<_Rep, _Period>& __rtime, 150*38fd1498Szrj _Predicate __p) 151*38fd1498Szrj { 152*38fd1498Szrj using __dur = typename __clock_t::duration; 153*38fd1498Szrj auto __reltime = chrono::duration_cast<__dur>(__rtime); 154*38fd1498Szrj if (__reltime < __rtime) 155*38fd1498Szrj ++__reltime; 156*38fd1498Szrj return wait_until(__lock, __clock_t::now() + __reltime, std::move(__p)); 157*38fd1498Szrj } 158*38fd1498Szrj 159*38fd1498Szrj native_handle_type 160*38fd1498Szrj native_handle() 161*38fd1498Szrj { return &_M_cond; } 162*38fd1498Szrj 163*38fd1498Szrj private: 164*38fd1498Szrj template<typename _Dur> 165*38fd1498Szrj cv_status 166*38fd1498Szrj __wait_until_impl(unique_lock<mutex>& __lock, 167*38fd1498Szrj const chrono::time_point<__clock_t, _Dur>& __atime) 168*38fd1498Szrj { 169*38fd1498Szrj auto __s = chrono::time_point_cast<chrono::seconds>(__atime); 170*38fd1498Szrj auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); 171*38fd1498Szrj 172*38fd1498Szrj __gthread_time_t __ts = 173*38fd1498Szrj { 174*38fd1498Szrj static_cast<std::time_t>(__s.time_since_epoch().count()), 175*38fd1498Szrj static_cast<long>(__ns.count()) 176*38fd1498Szrj }; 177*38fd1498Szrj 178*38fd1498Szrj __gthread_cond_timedwait(&_M_cond, __lock.mutex()->native_handle(), 179*38fd1498Szrj &__ts); 180*38fd1498Szrj 181*38fd1498Szrj return (__clock_t::now() < __atime 182*38fd1498Szrj ? cv_status::no_timeout : cv_status::timeout); 183*38fd1498Szrj } 184*38fd1498Szrj }; 185*38fd1498Szrj 186*38fd1498Szrj void 187*38fd1498Szrj notify_all_at_thread_exit(condition_variable&, unique_lock<mutex>); 188*38fd1498Szrj 189*38fd1498Szrj struct __at_thread_exit_elt 190*38fd1498Szrj { 191*38fd1498Szrj __at_thread_exit_elt* _M_next; 192*38fd1498Szrj void (*_M_cb)(void*); 193*38fd1498Szrj }; 194*38fd1498Szrj 195*38fd1498Szrj inline namespace _V2 { 196*38fd1498Szrj 197*38fd1498Szrj /// condition_variable_any 198*38fd1498Szrj // Like above, but mutex is not required to have try_lock. 199*38fd1498Szrj class condition_variable_any 200*38fd1498Szrj { 201*38fd1498Szrj typedef chrono::system_clock __clock_t; 202*38fd1498Szrj condition_variable _M_cond; 203*38fd1498Szrj shared_ptr<mutex> _M_mutex; 204*38fd1498Szrj 205*38fd1498Szrj // scoped unlock - unlocks in ctor, re-locks in dtor 206*38fd1498Szrj template<typename _Lock> 207*38fd1498Szrj struct _Unlock 208*38fd1498Szrj { 209*38fd1498Szrj explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); } 210*38fd1498Szrj 211*38fd1498Szrj ~_Unlock() noexcept(false) 212*38fd1498Szrj { 213*38fd1498Szrj if (uncaught_exception()) 214*38fd1498Szrj { 215*38fd1498Szrj __try 216*38fd1498Szrj { _M_lock.lock(); } 217*38fd1498Szrj __catch(const __cxxabiv1::__forced_unwind&) 218*38fd1498Szrj { __throw_exception_again; } 219*38fd1498Szrj __catch(...) 220*38fd1498Szrj { } 221*38fd1498Szrj } 222*38fd1498Szrj else 223*38fd1498Szrj _M_lock.lock(); 224*38fd1498Szrj } 225*38fd1498Szrj 226*38fd1498Szrj _Unlock(const _Unlock&) = delete; 227*38fd1498Szrj _Unlock& operator=(const _Unlock&) = delete; 228*38fd1498Szrj 229*38fd1498Szrj _Lock& _M_lock; 230*38fd1498Szrj }; 231*38fd1498Szrj 232*38fd1498Szrj public: 233*38fd1498Szrj condition_variable_any() : _M_mutex(std::make_shared<mutex>()) { } 234*38fd1498Szrj ~condition_variable_any() = default; 235*38fd1498Szrj 236*38fd1498Szrj condition_variable_any(const condition_variable_any&) = delete; 237*38fd1498Szrj condition_variable_any& operator=(const condition_variable_any&) = delete; 238*38fd1498Szrj 239*38fd1498Szrj void 240*38fd1498Szrj notify_one() noexcept 241*38fd1498Szrj { 242*38fd1498Szrj lock_guard<mutex> __lock(*_M_mutex); 243*38fd1498Szrj _M_cond.notify_one(); 244*38fd1498Szrj } 245*38fd1498Szrj 246*38fd1498Szrj void 247*38fd1498Szrj notify_all() noexcept 248*38fd1498Szrj { 249*38fd1498Szrj lock_guard<mutex> __lock(*_M_mutex); 250*38fd1498Szrj _M_cond.notify_all(); 251*38fd1498Szrj } 252*38fd1498Szrj 253*38fd1498Szrj template<typename _Lock> 254*38fd1498Szrj void 255*38fd1498Szrj wait(_Lock& __lock) 256*38fd1498Szrj { 257*38fd1498Szrj shared_ptr<mutex> __mutex = _M_mutex; 258*38fd1498Szrj unique_lock<mutex> __my_lock(*__mutex); 259*38fd1498Szrj _Unlock<_Lock> __unlock(__lock); 260*38fd1498Szrj // *__mutex must be unlocked before re-locking __lock so move 261*38fd1498Szrj // ownership of *__mutex lock to an object with shorter lifetime. 262*38fd1498Szrj unique_lock<mutex> __my_lock2(std::move(__my_lock)); 263*38fd1498Szrj _M_cond.wait(__my_lock2); 264*38fd1498Szrj } 265*38fd1498Szrj 266*38fd1498Szrj 267*38fd1498Szrj template<typename _Lock, typename _Predicate> 268*38fd1498Szrj void 269*38fd1498Szrj wait(_Lock& __lock, _Predicate __p) 270*38fd1498Szrj { 271*38fd1498Szrj while (!__p()) 272*38fd1498Szrj wait(__lock); 273*38fd1498Szrj } 274*38fd1498Szrj 275*38fd1498Szrj template<typename _Lock, typename _Clock, typename _Duration> 276*38fd1498Szrj cv_status 277*38fd1498Szrj wait_until(_Lock& __lock, 278*38fd1498Szrj const chrono::time_point<_Clock, _Duration>& __atime) 279*38fd1498Szrj { 280*38fd1498Szrj shared_ptr<mutex> __mutex = _M_mutex; 281*38fd1498Szrj unique_lock<mutex> __my_lock(*__mutex); 282*38fd1498Szrj _Unlock<_Lock> __unlock(__lock); 283*38fd1498Szrj // *__mutex must be unlocked before re-locking __lock so move 284*38fd1498Szrj // ownership of *__mutex lock to an object with shorter lifetime. 285*38fd1498Szrj unique_lock<mutex> __my_lock2(std::move(__my_lock)); 286*38fd1498Szrj return _M_cond.wait_until(__my_lock2, __atime); 287*38fd1498Szrj } 288*38fd1498Szrj 289*38fd1498Szrj template<typename _Lock, typename _Clock, 290*38fd1498Szrj typename _Duration, typename _Predicate> 291*38fd1498Szrj bool 292*38fd1498Szrj wait_until(_Lock& __lock, 293*38fd1498Szrj const chrono::time_point<_Clock, _Duration>& __atime, 294*38fd1498Szrj _Predicate __p) 295*38fd1498Szrj { 296*38fd1498Szrj while (!__p()) 297*38fd1498Szrj if (wait_until(__lock, __atime) == cv_status::timeout) 298*38fd1498Szrj return __p(); 299*38fd1498Szrj return true; 300*38fd1498Szrj } 301*38fd1498Szrj 302*38fd1498Szrj template<typename _Lock, typename _Rep, typename _Period> 303*38fd1498Szrj cv_status 304*38fd1498Szrj wait_for(_Lock& __lock, const chrono::duration<_Rep, _Period>& __rtime) 305*38fd1498Szrj { return wait_until(__lock, __clock_t::now() + __rtime); } 306*38fd1498Szrj 307*38fd1498Szrj template<typename _Lock, typename _Rep, 308*38fd1498Szrj typename _Period, typename _Predicate> 309*38fd1498Szrj bool 310*38fd1498Szrj wait_for(_Lock& __lock, 311*38fd1498Szrj const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p) 312*38fd1498Szrj { return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); } 313*38fd1498Szrj }; 314*38fd1498Szrj 315*38fd1498Szrj } // end inline namespace 316*38fd1498Szrj 317*38fd1498Szrj // @} group condition_variables 318*38fd1498Szrj_GLIBCXX_END_NAMESPACE_VERSION 319*38fd1498Szrj} // namespace 320*38fd1498Szrj 321*38fd1498Szrj#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1 322*38fd1498Szrj 323*38fd1498Szrj#endif // C++11 324*38fd1498Szrj 325*38fd1498Szrj#endif // _GLIBCXX_CONDITION_VARIABLE 326