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