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