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