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 |