xref: /aosp_15_r20/external/cronet/base/synchronization/condition_variable.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // ConditionVariable wraps pthreads condition variable synchronization or, on
6*6777b538SAndroid Build Coastguard Worker // Windows, simulates it.  This functionality is very helpful for having
7*6777b538SAndroid Build Coastguard Worker // several threads wait for an event, as is common with a thread pool managed
8*6777b538SAndroid Build Coastguard Worker // by a master.  The meaning of such an event in the (worker) thread pool
9*6777b538SAndroid Build Coastguard Worker // scenario is that additional tasks are now available for processing.  It is
10*6777b538SAndroid Build Coastguard Worker // used in Chrome in the DNS prefetching system to notify worker threads that
11*6777b538SAndroid Build Coastguard Worker // a queue now has items (tasks) which need to be tended to.  A related use
12*6777b538SAndroid Build Coastguard Worker // would have a pool manager waiting on a ConditionVariable, waiting for a
13*6777b538SAndroid Build Coastguard Worker // thread in the pool to announce (signal) that there is now more room in a
14*6777b538SAndroid Build Coastguard Worker // (bounded size) communications queue for the manager to deposit tasks, or,
15*6777b538SAndroid Build Coastguard Worker // as a second example, that the queue of tasks is completely empty and all
16*6777b538SAndroid Build Coastguard Worker // workers are waiting.
17*6777b538SAndroid Build Coastguard Worker //
18*6777b538SAndroid Build Coastguard Worker // USAGE NOTE 1: spurious signal events are possible with this and
19*6777b538SAndroid Build Coastguard Worker // most implementations of condition variables.  As a result, be
20*6777b538SAndroid Build Coastguard Worker // *sure* to retest your condition before proceeding.  The following
21*6777b538SAndroid Build Coastguard Worker // is a good example of doing this correctly:
22*6777b538SAndroid Build Coastguard Worker //
23*6777b538SAndroid Build Coastguard Worker // while (!work_to_be_done()) Wait(...);
24*6777b538SAndroid Build Coastguard Worker //
25*6777b538SAndroid Build Coastguard Worker // In contrast do NOT do the following:
26*6777b538SAndroid Build Coastguard Worker //
27*6777b538SAndroid Build Coastguard Worker // if (!work_to_be_done()) Wait(...);  // Don't do this.
28*6777b538SAndroid Build Coastguard Worker //
29*6777b538SAndroid Build Coastguard Worker // Especially avoid the above if you are relying on some other thread only
30*6777b538SAndroid Build Coastguard Worker // issuing a signal up *if* there is work-to-do.  There can/will
31*6777b538SAndroid Build Coastguard Worker // be spurious signals.  Recheck state on waiting thread before
32*6777b538SAndroid Build Coastguard Worker // assuming the signal was intentional. Caveat caller ;-).
33*6777b538SAndroid Build Coastguard Worker //
34*6777b538SAndroid Build Coastguard Worker // USAGE NOTE 2: Broadcast() frees up all waiting threads at once,
35*6777b538SAndroid Build Coastguard Worker // which leads to contention for the locks they all held when they
36*6777b538SAndroid Build Coastguard Worker // called Wait().  This results in POOR performance.  A much better
37*6777b538SAndroid Build Coastguard Worker // approach to getting a lot of threads out of Wait() is to have each
38*6777b538SAndroid Build Coastguard Worker // thread (upon exiting Wait()) call Signal() to free up another
39*6777b538SAndroid Build Coastguard Worker // Wait'ing thread.  Look at condition_variable_unittest.cc for
40*6777b538SAndroid Build Coastguard Worker // both examples.
41*6777b538SAndroid Build Coastguard Worker //
42*6777b538SAndroid Build Coastguard Worker // Broadcast() can be used nicely during teardown, as it gets the job
43*6777b538SAndroid Build Coastguard Worker // done, and leaves no sleeping threads... and performance is less
44*6777b538SAndroid Build Coastguard Worker // critical at that point.
45*6777b538SAndroid Build Coastguard Worker //
46*6777b538SAndroid Build Coastguard Worker // The semantics of Broadcast() are carefully crafted so that *all*
47*6777b538SAndroid Build Coastguard Worker // threads that were waiting when the request was made will indeed
48*6777b538SAndroid Build Coastguard Worker // get signaled.  Some implementations mess up, and don't signal them
49*6777b538SAndroid Build Coastguard Worker // all, while others allow the wait to be effectively turned off (for
50*6777b538SAndroid Build Coastguard Worker // a while while waiting threads come around).  This implementation
51*6777b538SAndroid Build Coastguard Worker // appears correct, as it will not "lose" any signals, and will guarantee
52*6777b538SAndroid Build Coastguard Worker // that all threads get signaled by Broadcast().
53*6777b538SAndroid Build Coastguard Worker //
54*6777b538SAndroid Build Coastguard Worker // This implementation offers support for "performance" in its selection of
55*6777b538SAndroid Build Coastguard Worker // which thread to revive.  Performance, in direct contrast with "fairness,"
56*6777b538SAndroid Build Coastguard Worker // assures that the thread that most recently began to Wait() is selected by
57*6777b538SAndroid Build Coastguard Worker // Signal to revive.  Fairness would (if publicly supported) assure that the
58*6777b538SAndroid Build Coastguard Worker // thread that has Wait()ed the longest is selected. The default policy
59*6777b538SAndroid Build Coastguard Worker // may improve performance, as the selected thread may have a greater chance of
60*6777b538SAndroid Build Coastguard Worker // having some of its stack data in various CPU caches.
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker #ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
63*6777b538SAndroid Build Coastguard Worker #define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
66*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
67*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
68*6777b538SAndroid Build Coastguard Worker 
69*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
70*6777b538SAndroid Build Coastguard Worker #include <pthread.h>
71*6777b538SAndroid Build Coastguard Worker #endif
72*6777b538SAndroid Build Coastguard Worker 
73*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
74*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/lock.h"
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
77*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_types.h"
78*6777b538SAndroid Build Coastguard Worker #endif
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker namespace base {
81*6777b538SAndroid Build Coastguard Worker 
82*6777b538SAndroid Build Coastguard Worker class TimeDelta;
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT ConditionVariable {
85*6777b538SAndroid Build Coastguard Worker  public:
86*6777b538SAndroid Build Coastguard Worker   // Construct a cv for use with ONLY one user lock.
87*6777b538SAndroid Build Coastguard Worker   explicit ConditionVariable(Lock* user_lock);
88*6777b538SAndroid Build Coastguard Worker 
89*6777b538SAndroid Build Coastguard Worker   ConditionVariable(const ConditionVariable&) = delete;
90*6777b538SAndroid Build Coastguard Worker   ConditionVariable& operator=(const ConditionVariable&) = delete;
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker   ~ConditionVariable();
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_APPLE)
95*6777b538SAndroid Build Coastguard Worker   // Initializes features for this class. See `base::features::Init()`.
96*6777b538SAndroid Build Coastguard Worker   static void InitializeFeatures();
97*6777b538SAndroid Build Coastguard Worker #endif
98*6777b538SAndroid Build Coastguard Worker 
99*6777b538SAndroid Build Coastguard Worker   // Wait() releases the caller's critical section atomically as it starts to
100*6777b538SAndroid Build Coastguard Worker   // sleep, and the reacquires it when it is signaled. The wait functions are
101*6777b538SAndroid Build Coastguard Worker   // susceptible to spurious wakeups. (See usage note 1 for more details.)
102*6777b538SAndroid Build Coastguard Worker   NOT_TAIL_CALLED void Wait();
103*6777b538SAndroid Build Coastguard Worker   NOT_TAIL_CALLED void TimedWait(const TimeDelta& max_time);
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker   // Broadcast() revives all waiting threads. (See usage note 2 for more
106*6777b538SAndroid Build Coastguard Worker   // details.)
107*6777b538SAndroid Build Coastguard Worker   void Broadcast();
108*6777b538SAndroid Build Coastguard Worker   // Signal() revives one waiting thread.
109*6777b538SAndroid Build Coastguard Worker   void Signal();
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   // Declares that this ConditionVariable will only ever be used by a thread
112*6777b538SAndroid Build Coastguard Worker   // that is idle at the bottom of its stack and waiting for work (in
113*6777b538SAndroid Build Coastguard Worker   // particular, it is not synchronously waiting on this ConditionVariable
114*6777b538SAndroid Build Coastguard Worker   // before resuming ongoing work). This is useful to avoid telling
115*6777b538SAndroid Build Coastguard Worker   // base-internals that this thread is "blocked" when it's merely idle and
116*6777b538SAndroid Build Coastguard Worker   // ready to do work. As such, this is only expected to be used by thread and
117*6777b538SAndroid Build Coastguard Worker   // thread pool impls.
declare_only_used_while_idle()118*6777b538SAndroid Build Coastguard Worker   void declare_only_used_while_idle() { waiting_is_blocking_ = false; }
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker  private:
121*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
122*6777b538SAndroid Build Coastguard Worker   CHROME_CONDITION_VARIABLE cv_;
123*6777b538SAndroid Build Coastguard Worker   const raw_ptr<CHROME_SRWLOCK> srwlock_;
124*6777b538SAndroid Build Coastguard Worker #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
125*6777b538SAndroid Build Coastguard Worker   pthread_cond_t condition_;
126*6777b538SAndroid Build Coastguard Worker   raw_ptr<pthread_mutex_t> user_mutex_;
127*6777b538SAndroid Build Coastguard Worker #endif
128*6777b538SAndroid Build Coastguard Worker 
129*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
130*6777b538SAndroid Build Coastguard Worker   const raw_ptr<base::Lock>
131*6777b538SAndroid Build Coastguard Worker       user_lock_;  // Needed to adjust shadow lock state on wait.
132*6777b538SAndroid Build Coastguard Worker #endif
133*6777b538SAndroid Build Coastguard Worker 
134*6777b538SAndroid Build Coastguard Worker   // Whether a thread invoking Wait() on this ConditionalVariable should be
135*6777b538SAndroid Build Coastguard Worker   // considered blocked as opposed to idle (and potentially replaced if part of
136*6777b538SAndroid Build Coastguard Worker   // a pool).
137*6777b538SAndroid Build Coastguard Worker   bool waiting_is_blocking_ = true;
138*6777b538SAndroid Build Coastguard Worker };
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker }  // namespace base
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker #endif  // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
143