Line data Source code
1 : /*
2 : * Copyright 2004 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 : #ifndef WEBRTC_BASE_CRITICALSECTION_H_
12 : #define WEBRTC_BASE_CRITICALSECTION_H_
13 :
14 : #include "webrtc/base/atomicops.h"
15 : #include "webrtc/base/checks.h"
16 : #include "webrtc/base/constructormagic.h"
17 : #include "webrtc/base/thread_annotations.h"
18 : #include "webrtc/base/platform_thread_types.h"
19 :
20 : #if defined(WEBRTC_WIN)
21 : // Include winsock2.h before including <windows.h> to maintain consistency with
22 : // win32.h. We can't include win32.h directly here since it pulls in
23 : // headers such as basictypes.h which causes problems in Chromium where webrtc
24 : // exists as two separate projects, webrtc and libjingle.
25 : #include <winsock2.h>
26 : #include <windows.h>
27 : #include <sal.h> // must come after windows headers.
28 : #endif // defined(WEBRTC_WIN)
29 :
30 : #if defined(WEBRTC_POSIX)
31 : #include <pthread.h>
32 : #endif
33 :
34 : // See notes in the 'Performance' unit test for the effects of this flag.
35 : #define USE_NATIVE_MUTEX_ON_MAC 0
36 :
37 : #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
38 : #include <dispatch/dispatch.h>
39 : #endif
40 :
41 : #define CS_DEBUG_CHECKS RTC_DCHECK_IS_ON
42 :
43 : #if CS_DEBUG_CHECKS
44 : #define CS_DEBUG_CODE(x) x
45 : #else // !CS_DEBUG_CHECKS
46 : #define CS_DEBUG_CODE(x)
47 : #endif // !CS_DEBUG_CHECKS
48 :
49 : namespace rtc {
50 :
51 : // Locking methods (Enter, TryEnter, Leave)are const to permit protecting
52 : // members inside a const context without requiring mutable CriticalSections
53 : // everywhere.
54 : class LOCKABLE CriticalSection {
55 : public:
56 : CriticalSection();
57 : ~CriticalSection();
58 :
59 : void Enter() const EXCLUSIVE_LOCK_FUNCTION();
60 : bool TryEnter() const EXCLUSIVE_TRYLOCK_FUNCTION(true);
61 : void Leave() const UNLOCK_FUNCTION();
62 :
63 : private:
64 : // Use only for RTC_DCHECKing.
65 : bool CurrentThreadIsOwner() const;
66 :
67 : #if defined(WEBRTC_WIN)
68 : mutable CRITICAL_SECTION crit_;
69 : #elif defined(WEBRTC_POSIX)
70 : #if defined(WEBRTC_MAC) && !USE_NATIVE_MUTEX_ON_MAC
71 : // Number of times the lock has been locked + number of threads waiting.
72 : // TODO(tommi): We could use this number and subtract the recursion count
73 : // to find places where we have multiple threads contending on the same lock.
74 : mutable volatile int lock_queue_;
75 : // |recursion_| represents the recursion count + 1 for the thread that owns
76 : // the lock. Only modified by the thread that owns the lock.
77 : mutable int recursion_;
78 : // Used to signal a single waiting thread when the lock becomes available.
79 : mutable dispatch_semaphore_t semaphore_;
80 : // The thread that currently holds the lock. Required to handle recursion.
81 : mutable PlatformThreadRef owning_thread_;
82 : #else
83 : mutable pthread_mutex_t mutex_;
84 : #endif
85 : CS_DEBUG_CODE(mutable PlatformThreadRef thread_);
86 : CS_DEBUG_CODE(mutable int recursion_count_);
87 : #endif
88 : };
89 :
90 : // CritScope, for serializing execution through a scope.
91 : class SCOPED_LOCKABLE CritScope {
92 : public:
93 : explicit CritScope(const CriticalSection* cs) EXCLUSIVE_LOCK_FUNCTION(cs);
94 : ~CritScope() UNLOCK_FUNCTION();
95 : private:
96 : const CriticalSection* const cs_;
97 : RTC_DISALLOW_COPY_AND_ASSIGN(CritScope);
98 : };
99 :
100 : // Tries to lock a critical section on construction via
101 : // CriticalSection::TryEnter, and unlocks on destruction if the
102 : // lock was taken. Never blocks.
103 : //
104 : // IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
105 : // subsequent code. Users *must* check locked() to determine if the
106 : // lock was taken. If you're not calling locked(), you're doing it wrong!
107 : class TryCritScope {
108 : public:
109 : explicit TryCritScope(const CriticalSection* cs);
110 : ~TryCritScope();
111 : #if defined(WEBRTC_WIN)
112 : _Check_return_ bool locked() const;
113 : #else
114 : bool locked() const __attribute__ ((__warn_unused_result__));
115 : #endif
116 : private:
117 : const CriticalSection* const cs_;
118 : const bool locked_;
119 : CS_DEBUG_CODE(mutable bool lock_was_called_);
120 : RTC_DISALLOW_COPY_AND_ASSIGN(TryCritScope);
121 : };
122 :
123 : // A POD lock used to protect global variables. Do NOT use for other purposes.
124 : // No custom constructor or private data member should be added.
125 0 : class LOCKABLE GlobalLockPod {
126 : public:
127 : void Lock() EXCLUSIVE_LOCK_FUNCTION();
128 :
129 : void Unlock() UNLOCK_FUNCTION();
130 :
131 : volatile int lock_acquired;
132 : };
133 :
134 : class GlobalLock : public GlobalLockPod {
135 : public:
136 : GlobalLock();
137 : };
138 :
139 : // GlobalLockScope, for serializing execution through a scope.
140 : class SCOPED_LOCKABLE GlobalLockScope {
141 : public:
142 : explicit GlobalLockScope(GlobalLockPod* lock) EXCLUSIVE_LOCK_FUNCTION(lock);
143 : ~GlobalLockScope() UNLOCK_FUNCTION();
144 : private:
145 : GlobalLockPod* const lock_;
146 : RTC_DISALLOW_COPY_AND_ASSIGN(GlobalLockScope);
147 : };
148 :
149 : } // namespace rtc
150 :
151 : #endif // WEBRTC_BASE_CRITICALSECTION_H_
|