- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / criticalsection.h
1 /*
2  * libjingle
3  * Copyright 2004, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without 
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice, 
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products 
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef TALK_BASE_CRITICALSECTION_H__
29 #define TALK_BASE_CRITICALSECTION_H__
30
31 #include "talk/base/constructormagic.h"
32
33 #ifdef WIN32
34 #include "talk/base/win32.h"
35 #endif
36
37 #ifdef POSIX
38 #include <pthread.h>
39 #endif
40
41 #ifdef _DEBUG
42 #define CS_TRACK_OWNER 1
43 #endif  // _DEBUG
44
45 #if CS_TRACK_OWNER
46 #define TRACK_OWNER(x) x
47 #else  // !CS_TRACK_OWNER
48 #define TRACK_OWNER(x)
49 #endif  // !CS_TRACK_OWNER
50
51 namespace talk_base {
52
53 #ifdef WIN32
54 class CriticalSection {
55  public:
56   CriticalSection() {
57     InitializeCriticalSection(&crit_);
58     // Windows docs say 0 is not a valid thread id
59     TRACK_OWNER(thread_ = 0);
60   }
61   ~CriticalSection() {
62     DeleteCriticalSection(&crit_);
63   }
64   void Enter() {
65     EnterCriticalSection(&crit_);
66     TRACK_OWNER(thread_ = GetCurrentThreadId());
67   }
68   bool TryEnter() {
69     if (TryEnterCriticalSection(&crit_) != FALSE) {
70       TRACK_OWNER(thread_ = GetCurrentThreadId());
71       return true;
72     }
73     return false;
74   }
75   void Leave() {
76     TRACK_OWNER(thread_ = 0);
77     LeaveCriticalSection(&crit_);
78   }
79
80 #if CS_TRACK_OWNER
81   bool CurrentThreadIsOwner() const { return thread_ == GetCurrentThreadId(); }
82 #endif  // CS_TRACK_OWNER
83
84  private:
85   CRITICAL_SECTION crit_;
86   TRACK_OWNER(DWORD thread_);  // The section's owning thread id
87 };
88 #endif // WIN32
89
90 #ifdef POSIX
91 class CriticalSection {
92  public:
93   CriticalSection() {
94     pthread_mutexattr_t mutex_attribute;
95     pthread_mutexattr_init(&mutex_attribute);
96     pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
97     pthread_mutex_init(&mutex_, &mutex_attribute);
98     pthread_mutexattr_destroy(&mutex_attribute);
99     TRACK_OWNER(thread_ = 0);
100   }
101   ~CriticalSection() {
102     pthread_mutex_destroy(&mutex_);
103   }
104   void Enter() {
105     pthread_mutex_lock(&mutex_);
106     TRACK_OWNER(thread_ = pthread_self());
107   }
108   bool TryEnter() {
109     if (pthread_mutex_trylock(&mutex_) == 0) {
110       TRACK_OWNER(thread_ = pthread_self());
111       return true;
112     }
113     return false;
114   }
115   void Leave() {
116     TRACK_OWNER(thread_ = 0);
117     pthread_mutex_unlock(&mutex_);
118   }
119
120 #if CS_TRACK_OWNER
121   bool CurrentThreadIsOwner() const { return pthread_equal(thread_, pthread_self()); }
122 #endif  // CS_TRACK_OWNER
123
124  private:
125   pthread_mutex_t mutex_;
126   TRACK_OWNER(pthread_t thread_);
127 };
128 #endif // POSIX
129
130 // CritScope, for serializing execution through a scope.
131 class CritScope {
132  public:
133   explicit CritScope(CriticalSection *pcrit) {
134     pcrit_ = pcrit;
135     pcrit_->Enter();
136   }
137   ~CritScope() {
138     pcrit_->Leave();
139   }
140  private:
141   CriticalSection *pcrit_;
142   DISALLOW_COPY_AND_ASSIGN(CritScope);
143 };
144
145 // Tries to lock a critical section on construction via
146 // CriticalSection::TryEnter, and unlocks on destruction if the
147 // lock was taken. Never blocks.
148 //
149 // IMPORTANT: Unlike CritScope, the lock may not be owned by this thread in
150 // subsequent code. Users *must* check locked() to determine if the
151 // lock was taken. If you're not calling locked(), you're doing it wrong!
152 class TryCritScope {
153  public:
154   explicit TryCritScope(CriticalSection *pcrit) {
155     pcrit_ = pcrit;
156     locked_ = pcrit_->TryEnter();
157   }
158   ~TryCritScope() {
159     if (locked_) {
160       pcrit_->Leave();
161     }
162   }
163   bool locked() const {
164     return locked_;
165   }
166  private:
167   CriticalSection *pcrit_;
168   bool locked_;
169   DISALLOW_COPY_AND_ASSIGN(TryCritScope);
170 };
171
172 // TODO: Move this to atomicops.h, which can't be done easily because of
173 // complex compile rules.
174 class AtomicOps {
175  public:
176 #ifdef WIN32
177   // Assumes sizeof(int) == sizeof(LONG), which it is on Win32 and Win64.
178   static int Increment(int* i) {
179     return ::InterlockedIncrement(reinterpret_cast<LONG*>(i));
180   }
181   static int Decrement(int* i) {
182     return ::InterlockedDecrement(reinterpret_cast<LONG*>(i));
183   }
184 #else
185   static int Increment(int* i) {
186     return __sync_add_and_fetch(i, 1);
187   }
188   static int Decrement(int* i) {
189     return __sync_sub_and_fetch(i, 1);
190   }
191 #endif
192 };
193
194 } // namespace talk_base
195
196 #endif // TALK_BASE_CRITICALSECTION_H__