• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 namespace v8 {
17 namespace base {
18 
19 // Forward declarations.
20 class ConditionVariableEvent;
21 class 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 
36 class 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 = CONDITION_VARIABLE;
73 #elif V8_OS_STARBOARD
74   using NativeHandle = SbConditionVariable;
75 #endif
76 
native_handle()77   NativeHandle& native_handle() {
78     return native_handle_;
79   }
native_handle()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 //   }
98 using 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