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) V8_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 typedef CONDITION_VARIABLE NativeHandle; 67 #endif 68 native_handle()69 NativeHandle& native_handle() { 70 return native_handle_; 71 } native_handle()72 const NativeHandle& native_handle() const { 73 return native_handle_; 74 } 75 76 private: 77 NativeHandle native_handle_; 78 79 DISALLOW_COPY_AND_ASSIGN(ConditionVariable); 80 }; 81 82 83 // POD ConditionVariable initialized lazily (i.e. the first time Pointer() is 84 // called). 85 // Usage: 86 // static LazyConditionVariable my_condvar = 87 // LAZY_CONDITION_VARIABLE_INITIALIZER; 88 // 89 // void my_function() { 90 // LockGuard<Mutex> lock_guard(&my_mutex); 91 // my_condvar.Pointer()->Wait(&my_mutex); 92 // } 93 typedef LazyStaticInstance< 94 ConditionVariable, DefaultConstructTrait<ConditionVariable>, 95 ThreadSafeInitOnceTrait>::type LazyConditionVariable; 96 97 #define LAZY_CONDITION_VARIABLE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER 98 99 } // namespace base 100 } // namespace v8 101 102 #endif // V8_BASE_PLATFORM_CONDITION_VARIABLE_H_ 103