| 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 |