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