V8 Project
mutex.h
Go to the documentation of this file.
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_MUTEX_H_
6 #define V8_BASE_PLATFORM_MUTEX_H_
7 
9 #if V8_OS_WIN
10 #include "src/base/win32-headers.h"
11 #endif
12 #include "src/base/logging.h"
13 
14 #if V8_OS_POSIX
15 #include <pthread.h> // NOLINT
16 #endif
17 
18 namespace v8 {
19 namespace base {
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 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.
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 
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 
76 #ifdef DEBUG
77  DCHECK_EQ(1, level_);
78  level_--;
79 #endif
80  }
81 
83 #ifdef DEBUG
84  DCHECK_EQ(0, level_);
85  level_++;
86 #endif
87  }
88 
89  friend class ConditionVariable;
90 
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 //
106 
107 #define LAZY_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
108 
109 
110 // -----------------------------------------------------------------------------
111 // RecursiveMutex
112 //
113 // This class is a synchronization primitive that can be used to protect shared
114 // data from being simultaneously accessed by multiple threads. A recursive
115 // mutex offers exclusive, recursive ownership semantics:
116 // - A calling thread owns a recursive mutex for a period of time that starts
117 // when it successfully calls either |Lock()| or |TryLock()|. During this
118 // period, the thread may make additional calls to |Lock()| or |TryLock()|.
119 // The period of ownership ends when the thread makes a matching number of
120 // calls to |Unlock()|.
121 // - When a thread owns a recursive mutex, all other threads will block (for
122 // calls to |Lock()|) or receive a |false| return value (for |TryLock()|) if
123 // they attempt to claim ownership of the recursive mutex.
124 // - The maximum number of times that a recursive mutex may be locked is
125 // unspecified, but after that number is reached, calls to |Lock()| will
126 // probably abort the process and calls to |TryLock()| return false.
127 // The behavior of a program is undefined if a recursive mutex is destroyed
128 // while still owned by some thread. The RecursiveMutex class is non-copyable.
129 
130 class RecursiveMutex FINAL {
131  public:
134 
135  // Locks the mutex. If another thread has already locked the mutex, a call to
136  // |Lock()| will block execution until the lock is acquired. A thread may call
137  // |Lock()| on a recursive mutex repeatedly. Ownership will only be released
138  // after the thread makes a matching number of calls to |Unlock()|.
139  // The behavior is undefined if the mutex is not unlocked before being
140  // destroyed, i.e. some thread still owns it.
141  void Lock();
142 
143  // Unlocks the mutex if its level of ownership is 1 (there was exactly one
144  // more call to |Lock()| than there were calls to unlock() made by this
145  // thread), reduces the level of ownership by 1 otherwise. The mutex must be
146  // locked by the current thread of execution, otherwise, the behavior is
147  // undefined.
148  void Unlock();
149 
150  // Tries to lock the given mutex. Returns whether the mutex was
151  // successfully locked.
153 
154  // The implementation-defined native handle type.
155  typedef Mutex::NativeHandle NativeHandle;
156 
157  NativeHandle& native_handle() {
158  return native_handle_;
159  }
160  const NativeHandle& native_handle() const {
161  return native_handle_;
162  }
163 
164  private:
165  NativeHandle native_handle_;
166 #ifdef DEBUG
167  int level_;
168 #endif
169 
170  DISALLOW_COPY_AND_ASSIGN(RecursiveMutex);
171 };
172 
173 
174 // POD RecursiveMutex initialized lazily (i.e. the first time Pointer() is
175 // called).
176 // Usage:
177 // static LazyRecursiveMutex my_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER;
178 //
179 // void my_function() {
180 // LockGuard<RecursiveMutex> guard(my_mutex.Pointer());
181 // // Do something.
182 // }
183 //
184 typedef LazyStaticInstance<RecursiveMutex,
187 
188 #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
189 
190 
191 // -----------------------------------------------------------------------------
192 // LockGuard
193 //
194 // This class is a mutex wrapper that provides a convenient RAII-style mechanism
195 // for owning a mutex for the duration of a scoped block.
196 // When a LockGuard object is created, it attempts to take ownership of the
197 // mutex it is given. When control leaves the scope in which the LockGuard
198 // object was created, the LockGuard is destructed and the mutex is released.
199 // The LockGuard class is non-copyable.
200 
201 template <typename Mutex>
202 class LockGuard FINAL {
203  public:
204  explicit LockGuard(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
205  ~LockGuard() { mutex_->Unlock(); }
206 
207  private:
208  Mutex* mutex_;
209 
211 };
212 
213 } } // namespace v8::base
214 
215 #endif // V8_BASE_PLATFORM_MUTEX_H_
Mutex::NativeHandle NativeHandle
Definition: mutex.h:155
DISALLOW_COPY_AND_ASSIGN(Mutex)
DISALLOW_COPY_AND_ASSIGN(RecursiveMutex)
const NativeHandle & native_handle() const
Definition: mutex.h:65
void AssertUnheldAndMark()
Definition: mutex.h:82
void AssertHeldAndUnmark()
Definition: mutex.h:75
LockGuard(Mutex *mutex)
Definition: mutex.h:204
DISALLOW_COPY_AND_ASSIGN(LockGuard)
bool TryLock() WARN_UNUSED_RESULT
NativeHandle & native_handle()
Definition: mutex.h:62
Mutex * mutex_
Definition: mutex.h:208
#define WARN_UNUSED_RESULT
#define FINAL
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
LazyStaticInstance< Mutex, DefaultConstructTrait< Mutex >, ThreadSafeInitOnceTrait >::type LazyMutex
Definition: mutex.h:105
LazyStaticInstance< RecursiveMutex, DefaultConstructTrait< RecursiveMutex >, ThreadSafeInitOnceTrait >::type LazyRecursiveMutex
Definition: mutex.h:186
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define V8_INLINE
Definition: v8config.h:306