Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(516)

Side by Side Diff: webrtc/base/criticalsection.cc

Issue 2877023002: Move webrtc/{base => rtc_base} (Closed)
Patch Set: update presubmit.py and DEPS include rules Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | webrtc/base/criticalsection_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/base/criticalsection.h"
12
13 #include "webrtc/base/checks.h"
14 #include "webrtc/base/platform_thread.h"
15
16 // TODO(tommi): Split this file up to per-platform implementation files.
17
18 namespace rtc {
19
20 CriticalSection::CriticalSection() {
21 #if defined(WEBRTC_WIN)
22 InitializeCriticalSection(&crit_);
23 #elif defined(WEBRTC_POSIX)
24 # if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
25 lock_queue_ = 0;
26 owning_thread_ = 0;
27 recursion_ = 0;
28 semaphore_ = dispatch_semaphore_create(0);
29 # else
30 pthread_mutexattr_t mutex_attribute;
31 pthread_mutexattr_init(&mutex_attribute);
32 pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
33 pthread_mutex_init(&mutex_, &mutex_attribute);
34 pthread_mutexattr_destroy(&mutex_attribute);
35 # endif
36 CS_DEBUG_CODE(thread_ = 0);
37 CS_DEBUG_CODE(recursion_count_ = 0);
38 RTC_UNUSED(thread_);
39 RTC_UNUSED(recursion_count_);
40 #else
41 # error Unsupported platform.
42 #endif
43 }
44
45 CriticalSection::~CriticalSection() {
46 #if defined(WEBRTC_WIN)
47 DeleteCriticalSection(&crit_);
48 #elif defined(WEBRTC_POSIX)
49 # if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
50 dispatch_release(semaphore_);
51 # else
52 pthread_mutex_destroy(&mutex_);
53 # endif
54 #else
55 # error Unsupported platform.
56 #endif
57 }
58
59 void CriticalSection::Enter() const EXCLUSIVE_LOCK_FUNCTION() {
60 #if defined(WEBRTC_WIN)
61 EnterCriticalSection(&crit_);
62 #elif defined(WEBRTC_POSIX)
63 # if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
64 int spin = 3000;
65 PlatformThreadRef self = CurrentThreadRef();
66 bool have_lock = false;
67 do {
68 // Instead of calling TryEnter() in this loop, we do two interlocked
69 // operations, first a read-only one in order to avoid affecting the lock
70 // cache-line while spinning, in case another thread is using the lock.
71 if (!IsThreadRefEqual(owning_thread_, self)) {
72 if (AtomicOps::AcquireLoad(&lock_queue_) == 0) {
73 if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) == 0) {
74 have_lock = true;
75 break;
76 }
77 }
78 } else {
79 AtomicOps::Increment(&lock_queue_);
80 have_lock = true;
81 break;
82 }
83
84 sched_yield();
85 } while (--spin);
86
87 if (!have_lock && AtomicOps::Increment(&lock_queue_) > 1) {
88 // Owning thread cannot be the current thread since TryEnter() would
89 // have succeeded.
90 RTC_DCHECK(!IsThreadRefEqual(owning_thread_, self));
91 // Wait for the lock to become available.
92 dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
93 RTC_DCHECK(owning_thread_ == 0);
94 RTC_DCHECK(!recursion_);
95 }
96
97 owning_thread_ = self;
98 ++recursion_;
99
100 # else
101 pthread_mutex_lock(&mutex_);
102 # endif
103
104 # if CS_DEBUG_CHECKS
105 if (!recursion_count_) {
106 RTC_DCHECK(!thread_);
107 thread_ = CurrentThreadRef();
108 } else {
109 RTC_DCHECK(CurrentThreadIsOwner());
110 }
111 ++recursion_count_;
112 # endif
113 #else
114 # error Unsupported platform.
115 #endif
116 }
117
118 bool CriticalSection::TryEnter() const EXCLUSIVE_TRYLOCK_FUNCTION(true) {
119 #if defined(WEBRTC_WIN)
120 return TryEnterCriticalSection(&crit_) != FALSE;
121 #elif defined(WEBRTC_POSIX)
122 # if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
123 if (!IsThreadRefEqual(owning_thread_, CurrentThreadRef())) {
124 if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) != 0)
125 return false;
126 owning_thread_ = CurrentThreadRef();
127 RTC_DCHECK(!recursion_);
128 } else {
129 AtomicOps::Increment(&lock_queue_);
130 }
131 ++recursion_;
132 # else
133 if (pthread_mutex_trylock(&mutex_) != 0)
134 return false;
135 # endif
136 # if CS_DEBUG_CHECKS
137 if (!recursion_count_) {
138 RTC_DCHECK(!thread_);
139 thread_ = CurrentThreadRef();
140 } else {
141 RTC_DCHECK(CurrentThreadIsOwner());
142 }
143 ++recursion_count_;
144 # endif
145 return true;
146 #else
147 # error Unsupported platform.
148 #endif
149 }
150
151 void CriticalSection::Leave() const UNLOCK_FUNCTION() {
152 RTC_DCHECK(CurrentThreadIsOwner());
153 #if defined(WEBRTC_WIN)
154 LeaveCriticalSection(&crit_);
155 #elif defined(WEBRTC_POSIX)
156 # if CS_DEBUG_CHECKS
157 --recursion_count_;
158 RTC_DCHECK(recursion_count_ >= 0);
159 if (!recursion_count_)
160 thread_ = 0;
161 # endif
162 # if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
163 RTC_DCHECK(IsThreadRefEqual(owning_thread_, CurrentThreadRef()));
164 RTC_DCHECK_GE(recursion_, 0);
165 --recursion_;
166 if (!recursion_)
167 owning_thread_ = 0;
168
169 if (AtomicOps::Decrement(&lock_queue_) > 0 && !recursion_)
170 dispatch_semaphore_signal(semaphore_);
171 # else
172 pthread_mutex_unlock(&mutex_);
173 # endif
174 #else
175 # error Unsupported platform.
176 #endif
177 }
178
179 bool CriticalSection::CurrentThreadIsOwner() const {
180 #if defined(WEBRTC_WIN)
181 // OwningThread has type HANDLE but actually contains the Thread ID:
182 // http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member- of-critical-section-of-type-handle-when-it-is-de
183 // Converting through size_t avoids the VS 2015 warning C4312: conversion from
184 // 'type1' to 'type2' of greater size
185 return crit_.OwningThread ==
186 reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
187 #elif defined(WEBRTC_POSIX)
188 # if CS_DEBUG_CHECKS
189 return IsThreadRefEqual(thread_, CurrentThreadRef());
190 # else
191 return true;
192 # endif // CS_DEBUG_CHECKS
193 #else
194 # error Unsupported platform.
195 #endif
196 }
197
198 CritScope::CritScope(const CriticalSection* cs) : cs_(cs) { cs_->Enter(); }
199 CritScope::~CritScope() { cs_->Leave(); }
200
201 TryCritScope::TryCritScope(const CriticalSection* cs)
202 : cs_(cs), locked_(cs->TryEnter()) {
203 CS_DEBUG_CODE(lock_was_called_ = false);
204 RTC_UNUSED(lock_was_called_);
205 }
206
207 TryCritScope::~TryCritScope() {
208 CS_DEBUG_CODE(RTC_DCHECK(lock_was_called_));
209 if (locked_)
210 cs_->Leave();
211 }
212
213 bool TryCritScope::locked() const {
214 CS_DEBUG_CODE(lock_was_called_ = true);
215 return locked_;
216 }
217
218 void GlobalLockPod::Lock() {
219 #if !defined(WEBRTC_WIN) && (!defined(WEBRTC_MAC) || USE_NATIVE_MUTEX_ON_MAC)
220 const struct timespec ts_null = {0};
221 #endif
222
223 while (AtomicOps::CompareAndSwap(&lock_acquired, 0, 1)) {
224 #if defined(WEBRTC_WIN)
225 ::Sleep(0);
226 #elif defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
227 sched_yield();
228 #else
229 nanosleep(&ts_null, nullptr);
230 #endif
231 }
232 }
233
234 void GlobalLockPod::Unlock() {
235 int old_value = AtomicOps::CompareAndSwap(&lock_acquired, 1, 0);
236 RTC_DCHECK_EQ(1, old_value) << "Unlock called without calling Lock first";
237 }
238
239 GlobalLock::GlobalLock() {
240 lock_acquired = 0;
241 }
242
243 GlobalLockScope::GlobalLockScope(GlobalLockPod* lock)
244 : lock_(lock) {
245 lock_->Lock();
246 }
247
248 GlobalLockScope::~GlobalLockScope() {
249 lock_->Unlock();
250 }
251
252 } // namespace rtc
OLDNEW
« no previous file with comments | « webrtc/base/criticalsection.h ('k') | webrtc/base/criticalsection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698