1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef threading_ConditionVariable_h
8 #define threading_ConditionVariable_h
10 #include "mozilla/PlatformConditionVariable.h"
11 #include "mozilla/TimeStamp.h"
15 #if !defined(XP_WIN) && !defined(__wasi__)
19 #include "threading/LockGuard.h"
20 #include "threading/Mutex.h"
27 enum class CVStatus
{ NoTimeout
, Timeout
};
30 using UniqueLock
= LockGuard
<T
>;
32 // A poly-fill for std::condition_variable.
33 class ConditionVariable
{
37 ConditionVariable() = default;
38 ~ConditionVariable() = default;
40 // Wake one thread that is waiting on this condition.
41 void notify_one() { impl_
.notify_one(); }
43 // Wake all threads that are waiting on this condition.
44 void notify_all() { impl_
.notify_all(); }
46 // Block the current thread of execution until this condition variable is
47 // woken from another thread via notify_one or notify_all.
48 void wait(Mutex
& lock
) {
50 lock
.preUnlockChecks();
52 impl_
.wait(lock
.impl_
);
55 lock
.postLockChecks();
58 void wait(UniqueLock
<Mutex
>& lock
) { wait(lock
.lock
); }
60 // As with |wait|, block the current thread of execution until woken from
61 // another thread. This method will resume waiting once woken until the given
62 // Predicate |pred| evaluates to true.
63 template <typename Predicate
>
64 void wait(UniqueLock
<Mutex
>& lock
, Predicate pred
) {
70 // Block the current thread of execution until woken from another thread, or
71 // the given absolute time is reached. The given absolute time is evaluated
72 // when this method is called, so will wake up after (abs_time - now),
73 // independent of system clock changes. While insulated from clock changes,
74 // this API is succeptible to the issues discussed above wait_for.
75 CVStatus
wait_until(UniqueLock
<Mutex
>& lock
,
76 const mozilla::TimeStamp
& abs_time
) {
77 return wait_for(lock
, abs_time
- mozilla::TimeStamp::Now());
80 // As with |wait_until|, block the current thread of execution until woken
81 // from another thread, or the given absolute time is reached. This method
82 // will resume waiting once woken until the given Predicate |pred| evaluates
84 template <typename Predicate
>
85 bool wait_until(UniqueLock
<Mutex
>& lock
, const mozilla::TimeStamp
& abs_time
,
88 if (wait_until(lock
, abs_time
) == CVStatus::Timeout
) {
95 // Block the current thread of execution until woken from another thread, or
96 // the given time duration has elapsed. Given that the system may be
97 // interrupted between the callee and the actual wait beginning, this call
98 // has a minimum granularity of the system's scheduling interval, and may
99 // encounter substantially longer delays, depending on system load.
100 CVStatus
wait_for(UniqueLock
<Mutex
>& lock
,
101 const mozilla::TimeDuration
& rel_time
) {
103 lock
.lock
.preUnlockChecks();
106 impl_
.wait_for(lock
.lock
.impl_
, rel_time
) == mozilla::CVStatus::Timeout
108 : CVStatus::NoTimeout
;
110 lock
.lock
.preLockChecks();
111 lock
.lock
.postLockChecks();
116 // As with |wait_for|, block the current thread of execution until woken from
117 // another thread or the given time duration has elapsed. This method will
118 // resume waiting once woken until the given Predicate |pred| evaluates to
120 template <typename Predicate
>
121 bool wait_for(UniqueLock
<Mutex
>& lock
, const mozilla::TimeDuration
& rel_time
,
123 return wait_until(lock
, mozilla::TimeStamp::Now() + rel_time
,
128 ConditionVariable(const ConditionVariable
&) = delete;
129 ConditionVariable
& operator=(const ConditionVariable
&) = delete;
131 friend class ExclusiveWaitableData
;
133 mozilla::detail::ConditionVariableImpl impl_
;
138 #endif // threading_ConditionVariable_h