xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/std/condition_variable (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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