15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ConditionVariable wraps pthreads condition variable synchronization or, on
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows, simulates it.  This functionality is very helpful for having
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// several threads wait for an event, as is common with a thread pool managed
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by a master.  The meaning of such an event in the (worker) thread pool
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scenario is that additional tasks are now available for processing.  It is
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used in Chrome in the DNS prefetching system to notify worker threads that
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a queue now has items (tasks) which need to be tended to.  A related use
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would have a pool manager waiting on a ConditionVariable, waiting for a
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread in the pool to announce (signal) that there is now more room in a
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (bounded size) communications queue for the manager to deposit tasks, or,
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as a second example, that the queue of tasks is completely empty and all
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// workers are waiting.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// USAGE NOTE 1: spurious signal events are possible with this and
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// most implementations of condition variables.  As a result, be
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// *sure* to retest your condition before proceeding.  The following
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is a good example of doing this correctly:
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// while (!work_to_be_done()) Wait(...);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In contrast do NOT do the following:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if (!work_to_be_done()) Wait(...);  // Don't do this.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Especially avoid the above if you are relying on some other thread only
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// issuing a signal up *if* there is work-to-do.  There can/will
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be spurious signals.  Recheck state on waiting thread before
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assuming the signal was intentional. Caveat caller ;-).
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// USAGE NOTE 2: Broadcast() frees up all waiting threads at once,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which leads to contention for the locks they all held when they
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called Wait().  This results in POOR performance.  A much better
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// approach to getting a lot of threads out of Wait() is to have each
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread (upon exiting Wait()) call Signal() to free up another
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wait'ing thread.  Look at condition_variable_unittest.cc for
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// both examples.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Broadcast() can be used nicely during teardown, as it gets the job
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// done, and leaves no sleeping threads... and performance is less
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// critical at that point.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The semantics of Broadcast() are carefully crafted so that *all*
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads that were waiting when the request was made will indeed
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// get signaled.  Some implementations mess up, and don't signal them
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all, while others allow the wait to be effectively turned off (for
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a while while waiting threads come around).  This implementation
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appears correct, as it will not "lose" any signals, and will guarantee
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that all threads get signaled by Broadcast().
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This implementation offers support for "performance" in its selection of
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which thread to revive.  Performance, in direct contrast with "fairness,"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// assures that the thread that most recently began to Wait() is selected by
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Signal to revive.  Fairness would (if publicly supported) assure that the
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread that has Wait()ed the longest is selected. The default policy
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may improve performance, as the selected thread may have a greater chance of
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// having some of its stack data in various CPU caches.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For a discussion of the many very subtle implementation details, see the FAQ
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at the end of condition_variable_win.cc.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ConditionVarImpl;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TimeDelta;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT ConditionVariable {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a cv for use with ONLY one user lock.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ConditionVariable(Lock* user_lock);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ConditionVariable();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait() releases the caller's critical section atomically as it starts to
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sleep, and the reacquires it when it is signaled.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Wait();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void TimedWait(const TimeDelta& max_time);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Broadcast() revives all waiting threads.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Broadcast();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Signal() revives one waiting thread.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Signal();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConditionVarImpl* impl_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_cond_t condition_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_mutex_t* user_mutex_;
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock* user_lock_;     // Needed to adjust shadow lock state on wait.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_
119