PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
critsec.h
Go to the documentation of this file.
1 /*
2 * critsec.h
3 *
4 * Critical section mutex class.
5 *
6 * Portable Windows Library
7 *
8 * Copyright (C) 2004 Post Increment
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Post Increment
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Revision: 30087 $
27 * $Author: rjongbloed $
28 * $Date: 2013-07-01 18:04:23 +1000 (Mon, 01 Jul 2013) $
29 */
30
31 #ifndef PTLIB_CRITICALSECTION_H
32 #define PTLIB_CRITICALSECTION_H
33
34 #include <ptlib/psync.h>
35
36 #if defined(SOLARIS) && !defined(__GNUC__)
37 #include <atomic.h>
38 #endif
39
40 #if P_HAS_ATOMIC_INT
41
42 #if defined(__GNUC__)
43 # if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
44 # include <ext/atomicity.h>
45 # else
46 # include <bits/atomicity.h>
47 # endif
48 #endif
49
50 #if P_NEEDS_GNU_CXX_NAMESPACE
51 #define EXCHANGE_AND_ADD(v,i) __gnu_cxx::__exchange_and_add(v,i)
52 #else
53 #define EXCHANGE_AND_ADD(v,i) __exchange_and_add(v,i)
54 #endif
55
56 #endif // P_HAS_ATOMIC_INT
57
58
65 #ifdef _WIN32
66
67 class PCriticalSection : public PSync
68 {
69 PCLASSINFO(PCriticalSection, PSync);
70
71 public:
76 PCriticalSection();
77
81 PCriticalSection(const PCriticalSection &);
82
85 ~PCriticalSection();
86
90 PCriticalSection & operator=(const PCriticalSection &) { return *this; }
92
97 PObject * Clone() const
98 {
99 return new PCriticalSection();
100 }
101
104 virtual void Wait();
105 inline void Enter() { Wait(); }
106
112 virtual PBoolean Wait(
113 const PTimeInterval & timeout // Amount of time to wait.
114 );
115
118 virtual void Signal();
119 inline void Leave() { Signal(); }
120
124 bool Try();
126
127
128 #include "msos/ptlib/critsec.h"
129
130 };
131
132 #endif
133
134 typedef PWaitAndSignal PEnterAndLeave;
135
136
137 class PAtomicBase
138 {
139 public:
140 #if defined(_WIN32)
141 typedef long IntegerType;
142 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
143 typedef __stl_atomic_t IntegerType;
144 #elif defined(SOLARIS) && !defined(__GNUC__)
145 typedef uint32_t IntegerType;
146 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
147 typedef _Atomic_word IntegerType;
148 #else
149 typedef int IntegerType;
150 protected:
151 pthread_mutex_t m_mutex;
152 #endif
153
154 protected:
155 IntegerType m_value;
156
157 explicit PAtomicBase(IntegerType value);
158
159 public:
161 ~PAtomicBase();
162 };
163
164
165
180 class PAtomicInteger : PAtomicBase
181 {
182 public:
183 typedef PAtomicBase::IntegerType IntegerType;
184
187 explicit PAtomicInteger(
188 IntegerType value = 0
189 ) : PAtomicBase(value) { }
190
192 __inline operator IntegerType() const { return m_value; }
193
195 __inline PAtomicInteger & operator=(IntegerType value) { m_value = value; return *this; }
196
198 void SetValue(
199 IntegerType value
200 ) { m_value = value; }
201
208 __inline bool IsZero() const { return m_value == 0; }
209
211 __inline bool operator!() const { return m_value == 0; }
212
218 IntegerType operator++();
219
225 IntegerType operator++(int);
226
232 IntegerType operator--();
233
239 IntegerType operator--(int);
240
241
242 friend __inline ostream & operator<<(ostream & strm, const PAtomicInteger & i)
243 {
244 return strm << i.m_value;
245 }
246 };
247
248
251 class PAtomicBoolean : PAtomicBase
252 {
253 public:
256 explicit PAtomicBoolean(
257 bool value = false
258 ) : PAtomicBase(value ? 1 : 0) { }
259
261 __inline operator bool() const { return m_value != 0; }
262
264 __inline PAtomicBoolean & operator=(bool value) { m_value = value ? 1 : 0; return *this; }
265
267 __inline bool operator!() const { return m_value == 0; }
268
272 bool TestAndSet(
273 bool value
274 );
275
276
277 friend __inline ostream & operator<<(ostream & strm, const PAtomicBoolean & b)
278 {
279 return strm << (b.m_value != 0 ? "true" : "false");
280 }
281 };
282
283
284 #if defined(_WIN32) || defined(DOC_PLUS_PLUS)
285 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
286 __inline PAtomicBase::~PAtomicBase() { }
287 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return InterlockedIncrement (&m_value); }
288 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return InterlockedExchangeAdd(&m_value, 1); }
289 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return InterlockedDecrement (&m_value); }
290 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return InterlockedExchangeAdd(&m_value, -1); }
291 __inline bool PAtomicBoolean::TestAndSet(bool value) { return InterlockedExchange (&m_value, value) != 0; }
292 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
293 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
294 __inline PAtomicBase::~PAtomicBase() { }
295 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return _STLP_ATOMIC_INCREMENT(&m_value); }
296 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return _STLP_ATOMIC_INCREMENT(&m_value)-1; }
297 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return _STLP_ATOMIC_DECREMENT(&m_value); }
298 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return _STLP_ATOMIC_DECREMENT(&m_value)+1; }
299 __inline bool PAtomicBoolean::TestAndSet(bool value) { return _STLP_ATOMIC_EXCHANGE (&m_value, value) != 0; }
300 #elif defined(SOLARIS) && !defined(__GNUC__)
301 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
302 __inline PAtomicBase::~PAtomicBase() { }
303 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return atomic_add_32_nv(&m_value, 1); }
304 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return atomic_add_32_nv(&m_value, 1)-1; }
305 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return atomic_add_32_nv(&m_value, -1); }
306 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return atomic_add_32_nv(&m_value, -1)+1; }
307 __inline bool PAtomicBoolean::TestAndSet(bool value) { return atomic_swap_32 (&m_value, value) != 0; }
308 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
309 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
310 __inline PAtomicBase::~PAtomicBase() { }
311 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return EXCHANGE_AND_ADD(&m_value, 1)+1; }
312 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return EXCHANGE_AND_ADD(&m_value, 1); }
313 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return EXCHANGE_AND_ADD(&m_value, -1)-1; }
314 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return EXCHANGE_AND_ADD(&m_value, -1); }
315 __inline bool PAtomicBoolean::TestAndSet(bool value) { IntegerType previous = value ? __sync_fetch_and_or(&m_value, 1) : __sync_fetch_and_and(&m_value, 0); return previous != 0; }
316 #else
317 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { pthread_mutex_init(&m_mutex, NULL); }
318 __inline PAtomicBase::~PAtomicBase() { pthread_mutex_destroy(&m_mutex); }
319 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { pthread_mutex_lock(&m_mutex); int retval = ++m_value; pthread_mutex_unlock(&m_mutex); return retval; }
320 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { pthread_mutex_lock(&m_mutex); int retval = m_value++; pthread_mutex_unlock(&m_mutex); return retval; }
321 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { pthread_mutex_lock(&m_mutex); int retval = --m_value; pthread_mutex_unlock(&m_mutex); return retval; }
322 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { pthread_mutex_lock(&m_mutex); int retval = m_value--; pthread_mutex_unlock(&m_mutex); return retval; }
323 __inline bool PAtomicBoolean::TestAndSet(bool value) { pthread_mutex_lock(&m_mutex); int retval = m_value; m_value = value; pthread_mutex_unlock(&m_mutex); return retval != 0; }
324 #endif
325
326
327 #endif // PTLIB_CRITICALSECTION_H
328
329
330 // End Of File ///////////////////////////////////////////////////////////////