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 11namespace v8 { 12namespace base { 13 14// Forward declarations. 15class ConditionVariableEvent; 16class 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 31class 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: 68 NativeHandle() : waitlist_(NULL), freelist_(NULL) {} 69 ~NativeHandle(); 70 71 Event* Pre() WARN_UNUSED_RESULT; 72 void Post(Event* event, bool result); 73 74 Mutex* mutex() { return &mutex_; } 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 86 NativeHandle& native_handle() { 87 return native_handle_; 88 } 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// } 110typedef 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