OLD | NEW |
(Empty) | |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #ifndef V8_PLATFORM_MUTEX_H_ |
| 29 #define V8_PLATFORM_MUTEX_H_ |
| 30 |
| 31 #include "lazy-instance.h" |
| 32 #if V8_OS_WIN |
| 33 #include "win32-headers.h" |
| 34 #endif |
| 35 |
| 36 #if V8_OS_POSIX |
| 37 #include <pthread.h> // NOLINT |
| 38 #endif |
| 39 |
| 40 namespace v8 { |
| 41 namespace internal { |
| 42 |
| 43 // ---------------------------------------------------------------------------- |
| 44 // Mutex |
| 45 // |
| 46 // This class is a synchronization primitive that can be used to protect shared |
| 47 // data from being simultaneously accessed by multiple threads. A mutex offers |
| 48 // exclusive, non-recursive ownership semantics: |
| 49 // - A calling thread owns a mutex from the time that it successfully calls |
| 50 // either |Lock()| or |TryLock()| until it calls |Unlock()|. |
| 51 // - When a thread owns a mutex, all other threads will block (for calls to |
| 52 // |Lock()|) or receive a |false| return value (for |TryLock()|) if they |
| 53 // attempt to claim ownership of the mutex. |
| 54 // A calling thread must not own the mutex prior to calling |Lock()| or |
| 55 // |TryLock()|. The behavior of a program is undefined if a mutex is destroyed |
| 56 // while still owned by some thread. The Mutex class is non-copyable. |
| 57 |
| 58 class Mutex V8_FINAL { |
| 59 public: |
| 60 Mutex(); |
| 61 ~Mutex(); |
| 62 |
| 63 // Locks the given mutex. If the mutex is currently unlocked, it becomes |
| 64 // locked and owned by the calling thread, and immediately. If the mutex |
| 65 // is already locked by another thread, suspends the calling thread until |
| 66 // the mutex is unlocked. |
| 67 void Lock(); |
| 68 |
| 69 // Unlocks the given mutex. The mutex is assumed to be locked and owned by |
| 70 // the calling thread on entrance. |
| 71 void Unlock(); |
| 72 |
| 73 // Tries to lock the given mutex. Returns whether the mutex was |
| 74 // successfully locked. |
| 75 bool TryLock() V8_WARN_UNUSED_RESULT; |
| 76 |
| 77 // The implementation-defined native handle type. |
| 78 #if V8_OS_POSIX |
| 79 typedef pthread_mutex_t NativeHandle; |
| 80 #elif V8_OS_WIN |
| 81 typedef CRITICAL_SECTION NativeHandle; |
| 82 #endif |
| 83 |
| 84 NativeHandle& native_handle() V8_WARN_UNUSED_RESULT { |
| 85 return native_handle_; |
| 86 } |
| 87 const NativeHandle& native_handle() const V8_WARN_UNUSED_RESULT { |
| 88 return native_handle_; |
| 89 } |
| 90 |
| 91 private: |
| 92 NativeHandle native_handle_; |
| 93 #ifdef DEBUG |
| 94 int level_; |
| 95 #endif |
| 96 |
| 97 DISALLOW_COPY_AND_ASSIGN(Mutex); |
| 98 }; |
| 99 |
| 100 |
| 101 // POD Mutex initialized lazily (i.e. the first time Pointer() is called). |
| 102 // Usage: |
| 103 // static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER; |
| 104 // |
| 105 // void my_function() { |
| 106 // LockGuard<Mutex> guard(my_mutex.Pointer()); |
| 107 // // Do something. |
| 108 // } |
| 109 // |
| 110 typedef LazyStaticInstance<Mutex, |
| 111 DefaultConstructTrait<Mutex>, |
| 112 ThreadSafeInitOnceTrait>::type LazyMutex; |
| 113 |
| 114 #define LAZY_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER |
| 115 |
| 116 |
| 117 // ----------------------------------------------------------------------------- |
| 118 // RecursiveMutex |
| 119 // |
| 120 // This class is a synchronization primitive that can be used to protect shared |
| 121 // data from being simultaneously accessed by multiple threads. A recursive |
| 122 // mutex offers exclusive, recursive ownership semantics: |
| 123 // - A calling thread owns a recursive mutex for a period of time that starts |
| 124 // when it successfully calls either |Lock()| or |TryLock()|. During this |
| 125 // period, the thread may make additional calls to |Lock()| or |TryLock()|. |
| 126 // The period of ownership ends when the thread makes a matching number of |
| 127 // calls to |Unlock()|. |
| 128 // - When a thread owns a recursive mutex, all other threads will block (for |
| 129 // calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if |
| 130 // they attempt to claim ownership of the recursive mutex. |
| 131 // - The maximum number of times that a recursive mutex may be locked is |
| 132 // unspecified, but after that number is reached, calls to |Lock()| will |
| 133 // probably abort the process and calls to |TryLock()| return false. |
| 134 // The behavior of a program is undefined if a recursive mutex is destroyed |
| 135 // while still owned by some thread. The RecursiveMutex class is non-copyable. |
| 136 |
| 137 class RecursiveMutex V8_FINAL { |
| 138 public: |
| 139 RecursiveMutex(); |
| 140 ~RecursiveMutex(); |
| 141 |
| 142 // Locks the mutex. If another thread has already locked the mutex, a call to |
| 143 // |Lock()| will block execution until the lock is acquired. A thread may call |
| 144 // |Lock()| on a recursive mutex repeatedly. Ownership will only be released |
| 145 // after the thread makes a matching number of calls to |Unlock()|. |
| 146 // The behavior is undefined if the mutex is not unlocked before being |
| 147 // destroyed, i.e. some thread still owns it. |
| 148 void Lock(); |
| 149 |
| 150 // Unlocks the mutex if its level of ownership is 1 (there was exactly one |
| 151 // more call to |Lock()| than there were calls to unlock() made by this |
| 152 // thread), reduces the level of ownership by 1 otherwise. The mutex must be |
| 153 // locked by the current thread of execution, otherwise, the behavior is |
| 154 // undefined. |
| 155 void Unlock(); |
| 156 |
| 157 // Tries to lock the given mutex. Returns whether the mutex was |
| 158 // successfully locked. |
| 159 bool TryLock() V8_WARN_UNUSED_RESULT; |
| 160 |
| 161 // The implementation-defined native handle type. |
| 162 typedef Mutex::NativeHandle NativeHandle; |
| 163 |
| 164 NativeHandle& native_handle() V8_WARN_UNUSED_RESULT { |
| 165 return native_handle_; |
| 166 } |
| 167 const NativeHandle& native_handle() const V8_WARN_UNUSED_RESULT { |
| 168 return native_handle_; |
| 169 } |
| 170 |
| 171 private: |
| 172 NativeHandle native_handle_; |
| 173 #ifdef DEBUG |
| 174 int level_; |
| 175 #endif |
| 176 |
| 177 DISALLOW_COPY_AND_ASSIGN(RecursiveMutex); |
| 178 }; |
| 179 |
| 180 |
| 181 // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is |
| 182 // called). |
| 183 // Usage: |
| 184 // static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER; |
| 185 // |
| 186 // void my_function() { |
| 187 // LockGuard<RecursiveMutex> guard(my_mutex.Pointer()); |
| 188 // // Do something. |
| 189 // } |
| 190 // |
| 191 typedef LazyStaticInstance<RecursiveMutex, |
| 192 DefaultConstructTrait<RecursiveMutex>, |
| 193 ThreadSafeInitOnceTrait>::type LazyRecursiveMutex; |
| 194 |
| 195 #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER |
| 196 |
| 197 |
| 198 // ----------------------------------------------------------------------------- |
| 199 // LockGuard |
| 200 // |
| 201 // This class is a mutex wrapper that provides a convenient RAII-style mechanism |
| 202 // for owning a mutex for the duration of a scoped block. |
| 203 // When a LockGuard object is created, it attempts to take ownership of the |
| 204 // mutex it is given. When control leaves the scope in which the LockGuard |
| 205 // object was created, the LockGuard is destructed and the mutex is released. |
| 206 // The LockGuard class is non-copyable. |
| 207 |
| 208 template <typename Mutex> |
| 209 class LockGuard V8_FINAL { |
| 210 public: |
| 211 explicit LockGuard(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); } |
| 212 ~LockGuard() { mutex_->Unlock(); } |
| 213 |
| 214 private: |
| 215 Mutex* mutex_; |
| 216 |
| 217 LockGuard(const LockGuard<Mutex>& other) V8_DELETE; |
| 218 LockGuard<Mutex>& operator=(const LockGuard<Mutex>& other) V8_DELETE; |
| 219 }; |
| 220 |
| 221 } } // namespace v8::internal |
| 222 |
| 223 #endif // V8_PLATFORM_MUTEX_H_ |
OLD | NEW |