1 // Copyright 2013 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_BASE_PLATFORM_CONDITION_VARIABLE_H_ 6 #define V8_BASE_PLATFORM_CONDITION_VARIABLE_H_ 7 8 #include "src/base/lazy-instance.h" 9 #include "src/base/platform/mutex.h" 10 11 namespace v8 { 12 namespace base { 13 14 // Forward declarations. 15 class ConditionVariableEvent; 16 class TimeDelta; 17 18 // ----------------------------------------------------------------------------- 19 // ConditionVariable 20 // 21 // This class is a synchronization primitive that can be used to block a thread, 22 // or multiple threads at the same time, until: 23 // - a notification is received from another thread, 24 // - a timeout expires, or 25 // - a spurious wakeup occurs 26 // Any thread that intends to wait on a ConditionVariable has to acquire a lock 27 // on a Mutex first. The |Wait()| and |WaitFor()| operations atomically release 28 // the mutex and suspend the execution of the calling thread. When the condition 29 // variable is notified, the thread is awakened, and the mutex is reacquired. 30 31 class ConditionVariable FINAL { 32 public: 33 ConditionVariable(); 34 ~ConditionVariable(); 35 36 // If any threads are waiting on this condition variable, calling 37 // |NotifyOne()| unblocks one of the waiting threads. 38 void NotifyOne(); 39 40 // Unblocks all threads currently waiting for this condition variable. 41 void NotifyAll(); 42 43 // |Wait()| causes the calling thread to block until the condition variable is 44 // notified or a spurious wakeup occurs. Atomically releases the mutex, blocks 45 // the current executing thread, and adds it to the list of threads waiting on 46 // this condition variable. The thread will be unblocked when |NotifyAll()| or 47 // |NotifyOne()| is executed. It may also be unblocked spuriously. When 48 // unblocked, regardless of the reason, the lock on the mutex is reacquired 49 // and |Wait()| exits. 50 void Wait(Mutex* mutex); 51 52 // Atomically releases the mutex, blocks the current executing thread, and 53 // adds it to the list of threads waiting on this condition variable. The 54 // thread will be unblocked when |NotifyAll()| or |NotifyOne()| is executed, 55 // or when the relative timeout |rel_time| expires. It may also be unblocked 56 // spuriously. When unblocked, regardless of the reason, the lock on the mutex 57 // is reacquired and |WaitFor()| exits. Returns true if the condition variable 58 // was notified prior to the timeout. 59 bool WaitFor(Mutex* mutex, const TimeDelta& rel_time) WARN_UNUSED_RESULT; 60 61 // The implementation-defined native handle type. 62 #if V8_OS_POSIX 63 typedef pthread_cond_t NativeHandle; 64 #elif V8_OS_WIN 65 struct Event; 66 class NativeHandle FINAL { 67 public: NativeHandle()68 NativeHandle() : waitlist_(NULL), freelist_(NULL) {} 69 ~NativeHandle(); 70 71 Event* Pre() WARN_UNUSED_RESULT; 72 void Post(Event* event, bool result); 73 mutex()74 Mutex* mutex() { return &mutex_; } waitlist()75 Event* waitlist() { return waitlist_; } 76 77 private: 78 Event* waitlist_; 79 Event* freelist_; 80 Mutex mutex_; 81 82 DISALLOW_COPY_AND_ASSIGN(NativeHandle); 83 }; 84 #endif 85 native_handle()86 NativeHandle& native_handle() { 87 return native_handle_; 88 } native_handle()89 const NativeHandle& native_handle() const { 90 return native_handle_; 91 } 92 93 private: 94 NativeHandle native_handle_; 95 96 DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 97 }; 98 99 100 // POD ConditionVariable initialized lazily (i.e. the first time Pointer() is 101 // called). 102 // Usage: 103 // static LazyConditionVariable my_condvar = 104 // LAZY_CONDITION_VARIABLE_INITIALIZER; 105 // 106 // void my_function() { 107 // LockGuard<Mutex> lock_guard(&my_mutex); 108 // my_condvar.Pointer()->Wait(&my_mutex); 109 // } 110 typedef LazyStaticInstance< 111 ConditionVariable, DefaultConstructTrait<ConditionVariable>, 112 ThreadSafeInitOnceTrait>::type LazyConditionVariable; 113 114 #define LAZY_CONDITION_VARIABLE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER 115 116 } } // namespace v8::base 117 118 #endif // V8_BASE_PLATFORM_CONDITION_VARIABLE_H_ 119