Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / js / src / threading / ConditionVariable.h
blobe2b8865cbf606430cabcc9931074dbac46346fa5
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"
13 #include <stdint.h>
14 #include <utility>
15 #if !defined(XP_WIN) && !defined(__wasi__)
16 # include <pthread.h>
17 #endif
19 #include "threading/LockGuard.h"
20 #include "threading/Mutex.h"
22 namespace js {
24 template <class T>
25 class ExclusiveData;
27 enum class CVStatus { NoTimeout, Timeout };
29 template <typename T>
30 using UniqueLock = LockGuard<T>;
32 // A poly-fill for std::condition_variable.
33 class ConditionVariable {
34 public:
35 struct PlatformData;
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) {
49 #ifdef DEBUG
50 lock.preUnlockChecks();
51 #endif
52 impl_.wait(lock.impl_);
53 #ifdef DEBUG
54 lock.preLockChecks();
55 lock.postLockChecks();
56 #endif
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) {
65 while (!pred()) {
66 wait(lock);
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
83 // to true.
84 template <typename Predicate>
85 bool wait_until(UniqueLock<Mutex>& lock, const mozilla::TimeStamp& abs_time,
86 Predicate pred) {
87 while (!pred()) {
88 if (wait_until(lock, abs_time) == CVStatus::Timeout) {
89 return pred();
92 return true;
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) {
102 #ifdef DEBUG
103 lock.lock.preUnlockChecks();
104 #endif
105 CVStatus res =
106 impl_.wait_for(lock.lock.impl_, rel_time) == mozilla::CVStatus::Timeout
107 ? CVStatus::Timeout
108 : CVStatus::NoTimeout;
109 #ifdef DEBUG
110 lock.lock.preLockChecks();
111 lock.lock.postLockChecks();
112 #endif
113 return res;
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
119 // true.
120 template <typename Predicate>
121 bool wait_for(UniqueLock<Mutex>& lock, const mozilla::TimeDuration& rel_time,
122 Predicate pred) {
123 return wait_until(lock, mozilla::TimeStamp::Now() + rel_time,
124 std::move(pred));
127 private:
128 ConditionVariable(const ConditionVariable&) = delete;
129 ConditionVariable& operator=(const ConditionVariable&) = delete;
130 template <class T>
131 friend class ExclusiveWaitableData;
133 mozilla::detail::ConditionVariableImpl impl_;
136 } // namespace js
138 #endif // threading_ConditionVariable_h