| OLD | NEW |
| (Empty) |
| 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_PLATFORM_MUTEX_H_ | |
| 6 #define V8_PLATFORM_MUTEX_H_ | |
| 7 | |
| 8 #include "src/base/lazy-instance.h" | |
| 9 #if V8_OS_WIN | |
| 10 #include "src/base/win32-headers.h" | |
| 11 #endif | |
| 12 #include "src/checks.h" | |
| 13 | |
| 14 #if V8_OS_POSIX | |
| 15 #include <pthread.h> // NOLINT | |
| 16 #endif | |
| 17 | |
| 18 namespace v8 { | |
| 19 namespace internal { | |
| 20 | |
| 21 // ---------------------------------------------------------------------------- | |
| 22 // Mutex | |
| 23 // | |
| 24 // This class is a synchronization primitive that can be used to protect shared | |
| 25 // data from being simultaneously accessed by multiple threads. A mutex offers | |
| 26 // exclusive, non-recursive ownership semantics: | |
| 27 // - A calling thread owns a mutex from the time that it successfully calls | |
| 28 // either |Lock()| or |TryLock()| until it calls |Unlock()|. | |
| 29 // - When a thread owns a mutex, all other threads will block (for calls to | |
| 30 // |Lock()|) or receive a |false| return value (for |TryLock()|) if they | |
| 31 // attempt to claim ownership of the mutex. | |
| 32 // A calling thread must not own the mutex prior to calling |Lock()| or | |
| 33 // |TryLock()|. The behavior of a program is undefined if a mutex is destroyed | |
| 34 // while still owned by some thread. The Mutex class is non-copyable. | |
| 35 | |
| 36 class Mutex V8_FINAL { | |
| 37 public: | |
| 38 Mutex(); | |
| 39 ~Mutex(); | |
| 40 | |
| 41 // Locks the given mutex. If the mutex is currently unlocked, it becomes | |
| 42 // locked and owned by the calling thread, and immediately. If the mutex | |
| 43 // is already locked by another thread, suspends the calling thread until | |
| 44 // the mutex is unlocked. | |
| 45 void Lock(); | |
| 46 | |
| 47 // Unlocks the given mutex. The mutex is assumed to be locked and owned by | |
| 48 // the calling thread on entrance. | |
| 49 void Unlock(); | |
| 50 | |
| 51 // Tries to lock the given mutex. Returns whether the mutex was | |
| 52 // successfully locked. | |
| 53 bool TryLock() V8_WARN_UNUSED_RESULT; | |
| 54 | |
| 55 // The implementation-defined native handle type. | |
| 56 #if V8_OS_POSIX | |
| 57 typedef pthread_mutex_t NativeHandle; | |
| 58 #elif V8_OS_WIN | |
| 59 typedef CRITICAL_SECTION NativeHandle; | |
| 60 #endif | |
| 61 | |
| 62 NativeHandle& native_handle() { | |
| 63 return native_handle_; | |
| 64 } | |
| 65 const NativeHandle& native_handle() const { | |
| 66 return native_handle_; | |
| 67 } | |
| 68 | |
| 69 private: | |
| 70 NativeHandle native_handle_; | |
| 71 #ifdef DEBUG | |
| 72 int level_; | |
| 73 #endif | |
| 74 | |
| 75 V8_INLINE void AssertHeldAndUnmark() { | |
| 76 #ifdef DEBUG | |
| 77 ASSERT_EQ(1, level_); | |
| 78 level_--; | |
| 79 #endif | |
| 80 } | |
| 81 | |
| 82 V8_INLINE void AssertUnheldAndMark() { | |
| 83 #ifdef DEBUG | |
| 84 ASSERT_EQ(0, level_); | |
| 85 level_++; | |
| 86 #endif | |
| 87 } | |
| 88 | |
| 89 friend class ConditionVariable; | |
| 90 | |
| 91 DISALLOW_COPY_AND_ASSIGN(Mutex); | |
| 92 }; | |
| 93 | |
| 94 | |
| 95 // POD Mutex initialized lazily (i.e. the first time Pointer() is called). | |
| 96 // Usage: | |
| 97 // static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER; | |
| 98 // | |
| 99 // void my_function() { | |
| 100 // LockGuard<Mutex> guard(my_mutex.Pointer()); | |
| 101 // // Do something. | |
| 102 // } | |
| 103 // | |
| 104 typedef v8::base::LazyStaticInstance< | |
| 105 Mutex, v8::base::DefaultConstructTrait<Mutex>, | |
| 106 v8::base::ThreadSafeInitOnceTrait>::type LazyMutex; | |
| 107 | |
| 108 #define LAZY_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER | |
| 109 | |
| 110 | |
| 111 // ----------------------------------------------------------------------------- | |
| 112 // RecursiveMutex | |
| 113 // | |
| 114 // This class is a synchronization primitive that can be used to protect shared | |
| 115 // data from being simultaneously accessed by multiple threads. A recursive | |
| 116 // mutex offers exclusive, recursive ownership semantics: | |
| 117 // - A calling thread owns a recursive mutex for a period of time that starts | |
| 118 // when it successfully calls either |Lock()| or |TryLock()|. During this | |
| 119 // period, the thread may make additional calls to |Lock()| or |TryLock()|. | |
| 120 // The period of ownership ends when the thread makes a matching number of | |
| 121 // calls to |Unlock()|. | |
| 122 // - When a thread owns a recursive mutex, all other threads will block (for | |
| 123 // calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if | |
| 124 // they attempt to claim ownership of the recursive mutex. | |
| 125 // - The maximum number of times that a recursive mutex may be locked is | |
| 126 // unspecified, but after that number is reached, calls to |Lock()| will | |
| 127 // probably abort the process and calls to |TryLock()| return false. | |
| 128 // The behavior of a program is undefined if a recursive mutex is destroyed | |
| 129 // while still owned by some thread. The RecursiveMutex class is non-copyable. | |
| 130 | |
| 131 class RecursiveMutex V8_FINAL { | |
| 132 public: | |
| 133 RecursiveMutex(); | |
| 134 ~RecursiveMutex(); | |
| 135 | |
| 136 // Locks the mutex. If another thread has already locked the mutex, a call to | |
| 137 // |Lock()| will block execution until the lock is acquired. A thread may call | |
| 138 // |Lock()| on a recursive mutex repeatedly. Ownership will only be released | |
| 139 // after the thread makes a matching number of calls to |Unlock()|. | |
| 140 // The behavior is undefined if the mutex is not unlocked before being | |
| 141 // destroyed, i.e. some thread still owns it. | |
| 142 void Lock(); | |
| 143 | |
| 144 // Unlocks the mutex if its level of ownership is 1 (there was exactly one | |
| 145 // more call to |Lock()| than there were calls to unlock() made by this | |
| 146 // thread), reduces the level of ownership by 1 otherwise. The mutex must be | |
| 147 // locked by the current thread of execution, otherwise, the behavior is | |
| 148 // undefined. | |
| 149 void Unlock(); | |
| 150 | |
| 151 // Tries to lock the given mutex. Returns whether the mutex was | |
| 152 // successfully locked. | |
| 153 bool TryLock() V8_WARN_UNUSED_RESULT; | |
| 154 | |
| 155 // The implementation-defined native handle type. | |
| 156 typedef Mutex::NativeHandle NativeHandle; | |
| 157 | |
| 158 NativeHandle& native_handle() { | |
| 159 return native_handle_; | |
| 160 } | |
| 161 const NativeHandle& native_handle() const { | |
| 162 return native_handle_; | |
| 163 } | |
| 164 | |
| 165 private: | |
| 166 NativeHandle native_handle_; | |
| 167 #ifdef DEBUG | |
| 168 int level_; | |
| 169 #endif | |
| 170 | |
| 171 DISALLOW_COPY_AND_ASSIGN(RecursiveMutex); | |
| 172 }; | |
| 173 | |
| 174 | |
| 175 // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is | |
| 176 // called). | |
| 177 // Usage: | |
| 178 // static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER; | |
| 179 // | |
| 180 // void my_function() { | |
| 181 // LockGuard<RecursiveMutex> guard(my_mutex.Pointer()); | |
| 182 // // Do something. | |
| 183 // } | |
| 184 // | |
| 185 typedef v8::base::LazyStaticInstance< | |
| 186 RecursiveMutex, v8::base::DefaultConstructTrait<RecursiveMutex>, | |
| 187 v8::base::ThreadSafeInitOnceTrait>::type LazyRecursiveMutex; | |
| 188 | |
| 189 #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER | |
| 190 | |
| 191 | |
| 192 // ----------------------------------------------------------------------------- | |
| 193 // LockGuard | |
| 194 // | |
| 195 // This class is a mutex wrapper that provides a convenient RAII-style mechanism | |
| 196 // for owning a mutex for the duration of a scoped block. | |
| 197 // When a LockGuard object is created, it attempts to take ownership of the | |
| 198 // mutex it is given. When control leaves the scope in which the LockGuard | |
| 199 // object was created, the LockGuard is destructed and the mutex is released. | |
| 200 // The LockGuard class is non-copyable. | |
| 201 | |
| 202 template <typename Mutex> | |
| 203 class LockGuard V8_FINAL { | |
| 204 public: | |
| 205 explicit LockGuard(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); } | |
| 206 ~LockGuard() { mutex_->Unlock(); } | |
| 207 | |
| 208 private: | |
| 209 Mutex* mutex_; | |
| 210 | |
| 211 DISALLOW_COPY_AND_ASSIGN(LockGuard); | |
| 212 }; | |
| 213 | |
| 214 } } // namespace v8::internal | |
| 215 | |
| 216 #endif // V8_PLATFORM_MUTEX_H_ | |
| OLD | NEW |