| // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | // ConditionVariable wraps pthreads condition variable synchronization or, on | 
 | // Windows, simulates it.  This functionality is very helpful for having | 
 | // several threads wait for an event, as is common with a thread pool managed | 
 | // by a master.  The meaning of such an event in the (worker) thread pool | 
 | // scenario is that additional tasks are now available for processing.  It is | 
 | // used in Chrome in the DNS prefetching system to notify worker threads that | 
 | // a queue now has items (tasks) which need to be tended to.  A related use | 
 | // would have a pool manager waiting on a ConditionVariable, waiting for a | 
 | // thread in the pool to announce (signal) that there is now more room in a | 
 | // (bounded size) communications queue for the manager to deposit tasks, or, | 
 | // as a second example, that the queue of tasks is completely empty and all | 
 | // workers are waiting. | 
 | // | 
 | // USAGE NOTE 1: spurious signal events are possible with this and | 
 | // most implementations of condition variables.  As a result, be | 
 | // *sure* to retest your condition before proceeding.  The following | 
 | // is a good example of doing this correctly: | 
 | // | 
 | // while (!work_to_be_done()) Wait(...); | 
 | // | 
 | // In contrast do NOT do the following: | 
 | // | 
 | // if (!work_to_be_done()) Wait(...);  // Don't do this. | 
 | // | 
 | // Especially avoid the above if you are relying on some other thread only | 
 | // issuing a signal up *if* there is work-to-do.  There can/will | 
 | // be spurious signals.  Recheck state on waiting thread before | 
 | // assuming the signal was intentional. Caveat caller ;-). | 
 | // | 
 | // USAGE NOTE 2: Broadcast() frees up all waiting threads at once, | 
 | // which leads to contention for the locks they all held when they | 
 | // called Wait().  This results in POOR performance.  A much better | 
 | // approach to getting a lot of threads out of Wait() is to have each | 
 | // thread (upon exiting Wait()) call Signal() to free up another | 
 | // Wait'ing thread.  Look at condition_variable_unittest.cc for | 
 | // both examples. | 
 | // | 
 | // Broadcast() can be used nicely during teardown, as it gets the job | 
 | // done, and leaves no sleeping threads... and performance is less | 
 | // critical at that point. | 
 | // | 
 | // The semantics of Broadcast() are carefully crafted so that *all* | 
 | // threads that were waiting when the request was made will indeed | 
 | // get signaled.  Some implementations mess up, and don't signal them | 
 | // all, while others allow the wait to be effectively turned off (for | 
 | // a while while waiting threads come around).  This implementation | 
 | // appears correct, as it will not "lose" any signals, and will guarantee | 
 | // that all threads get signaled by Broadcast(). | 
 | // | 
 | // This implementation offers support for "performance" in its selection of | 
 | // which thread to revive.  Performance, in direct contrast with "fairness," | 
 | // assures that the thread that most recently began to Wait() is selected by | 
 | // Signal to revive.  Fairness would (if publicly supported) assure that the | 
 | // thread that has Wait()ed the longest is selected. The default policy | 
 | // may improve performance, as the selected thread may have a greater chance of | 
 | // having some of its stack data in various CPU caches. | 
 | // | 
 | // For a discussion of the many very subtle implementation details, see the FAQ | 
 | // at the end of condition_variable_win.cc. | 
 |  | 
 | #ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ | 
 | #define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ | 
 |  | 
 | #if defined(OS_POSIX) || defined(OS_FUCHSIA) | 
 | #include <pthread.h> | 
 | #endif | 
 |  | 
 | #include "base/base_export.h" | 
 | #include "base/logging.h" | 
 | #include "base/macros.h" | 
 | #include "base/synchronization/lock.h" | 
 | #include "build/build_config.h" | 
 |  | 
 | #if defined(OS_WIN) | 
 | #include "base/win/windows_types.h" | 
 | #endif | 
 |  | 
 | namespace base { | 
 |  | 
 | class TimeDelta; | 
 |  | 
 | class BASE_EXPORT ConditionVariable { | 
 |  public: | 
 |   // Construct a cv for use with ONLY one user lock. | 
 |   explicit ConditionVariable(Lock* user_lock); | 
 |  | 
 |   ~ConditionVariable(); | 
 |  | 
 |   // Wait() releases the caller's critical section atomically as it starts to | 
 |   // sleep, and the reacquires it when it is signaled. The wait functions are | 
 |   // susceptible to spurious wakeups. (See usage note 1 for more details.) | 
 |   void Wait(); | 
 |   void TimedWait(const TimeDelta& max_time); | 
 |  | 
 |   // Broadcast() revives all waiting threads. (See usage note 2 for more | 
 |   // details.) | 
 |   void Broadcast(); | 
 |   // Signal() revives one waiting thread. | 
 |   void Signal(); | 
 |  | 
 |  private: | 
 |  | 
 | #if defined(OS_WIN) | 
 |   CHROME_CONDITION_VARIABLE cv_; | 
 |   CHROME_SRWLOCK* const srwlock_; | 
 | #elif defined(OS_POSIX) || defined(OS_FUCHSIA) | 
 |   pthread_cond_t condition_; | 
 |   pthread_mutex_t* user_mutex_; | 
 | #endif | 
 |  | 
 | #if DCHECK_IS_ON() | 
 |   base::Lock* const user_lock_;  // Needed to adjust shadow lock state on wait. | 
 | #endif | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(ConditionVariable); | 
 | }; | 
 |  | 
 | }  // namespace base | 
 |  | 
 | #endif  // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ |