PTLib  Version 2.10.10
 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: 29078 $
27  * $Author: rjongbloed $
28  * $Date: 2013-02-12 17:22:50 -0600 (Tue, 12 Feb 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 {
70 
71  public:
77 
82 
86 
90  PCriticalSection & operator=(const PCriticalSection &) { return *this; }
92 
97  PObject * Clone() const
98  {
99  return new PCriticalSection();
100  }
101 
104  void Wait();
105  inline void Enter() { Wait(); }
106 
109  void Signal();
110  inline void Leave() { Signal(); }
111 
115  bool Try();
117 
118 
119 #include "msos/ptlib/critsec.h"
120 
121 };
122 
123 #endif
124 
126 
127 
129 {
130  public:
131 #if defined(_WIN32)
132  typedef long IntegerType;
133 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
134  typedef __stl_atomic_t IntegerType;
135 #elif defined(SOLARIS) && !defined(__GNUC__)
136  typedef uint32_t IntegerType;
137 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
138  typedef _Atomic_word IntegerType;
139 #else
140  typedef int IntegerType;
141  protected:
142  pthread_mutex_t m_mutex;
143 #endif
144 
145  protected:
147 
148  explicit PAtomicBase(IntegerType value);
149 
150  public:
152  ~PAtomicBase();
153 };
154 
155 
156 
172 {
173  public:
175 
178  explicit PAtomicInteger(
179  IntegerType value = 0
180  ) : PAtomicBase(value) { }
181 
183  __inline operator IntegerType() const { return m_value; }
184 
186  __inline PAtomicInteger & operator=(IntegerType value) { m_value = value; return *this; }
187 
189  void SetValue(
190  IntegerType value
191  ) { m_value = value; }
192 
199  __inline bool IsZero() const { return m_value == 0; }
200 
202  __inline bool operator!() const { return m_value != 0; }
203 
204  friend __inline ostream & operator<<(ostream & strm, const PAtomicInteger & i)
205  {
206  return strm << i.m_value;
207  }
208 
215 
221  IntegerType operator++(int);
222 
229 
235  IntegerType operator--(int);
236 };
237 
238 
242 {
243  public:
246  explicit PAtomicBoolean(
247  bool value = false
248  ) : PAtomicBase(value ? 1 : 0) { }
249 
251  __inline operator bool() const { return m_value != 0; }
252 
254  __inline bool operator!() const { return m_value != 0; }
255 
257  __inline PAtomicBoolean & operator=(bool value) { m_value = value ? 1 : 0; return *this; }
258 
262  bool TestAndSet(
263  bool value
264  );
265 
266  friend __inline ostream & operator<<(ostream & strm, const PAtomicBoolean & b)
267  {
268  return strm << (b.m_value != 0 ? "true" : "false");
269  }
270 };
271 
272 
273 #if defined(_WIN32) || defined(DOC_PLUS_PLUS)
274 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
276 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return InterlockedIncrement (&m_value); }
277 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return InterlockedExchangeAdd(&m_value, 1); }
278 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return InterlockedDecrement (&m_value); }
279 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return InterlockedExchangeAdd(&m_value, -1); }
280 __inline bool PAtomicBoolean::TestAndSet(bool value) { return InterlockedExchange (&m_value, value) != 0; }
281 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
282 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
283 __inline PAtomicBase::~PAtomicBase() { }
284 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return _STLP_ATOMIC_INCREMENT(&m_value); }
285 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return _STLP_ATOMIC_INCREMENT(&m_value)-1; }
286 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return _STLP_ATOMIC_DECREMENT(&m_value); }
287 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return _STLP_ATOMIC_DECREMENT(&m_value)+1; }
288 __inline bool PAtomicBoolean::TestAndSet(bool value) { return _STLP_ATOMIC_EXCHANGE (&m_value, value) != 0; }
289 #elif defined(SOLARIS) && !defined(__GNUC__)
290 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
291 __inline PAtomicBase::~PAtomicBase() { }
292 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return atomic_add_32_nv(&m_value, 1); }
293 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return atomic_add_32_nv(&m_value, 1)-1; }
294 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return atomic_add_32_nv(&m_value, -1); }
295 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return atomic_add_32_nv(&m_value, -1)+1; }
296 __inline bool PAtomicBoolean::TestAndSet(bool value) { return atomic_swap_32 (&m_value, value) != 0; }
297 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
298 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
299 __inline PAtomicBase::~PAtomicBase() { }
300 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return EXCHANGE_AND_ADD(&m_value, 1)+1; }
301 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return EXCHANGE_AND_ADD(&m_value, 1); }
302 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return EXCHANGE_AND_ADD(&m_value, -1)-1; }
303 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return EXCHANGE_AND_ADD(&m_value, -1); }
304 __inline bool PAtomicBoolean::TestAndSet(bool value) { IntegerType previous = EXCHANGE_AND_ADD(&m_value, value?1:-1); m_value = value?1:0; return previous > 0; }
305 #else
306 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { pthread_mutex_init(&m_mutex, NULL); }
307 __inline PAtomicBase::~PAtomicBase() { pthread_mutex_destroy(&m_mutex); }
308 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { pthread_mutex_lock(&m_mutex); int retval = ++m_value; pthread_mutex_unlock(&m_mutex); return retval; }
309 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { pthread_mutex_lock(&m_mutex); int retval = m_value++; pthread_mutex_unlock(&m_mutex); return retval; }
310 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { pthread_mutex_lock(&m_mutex); int retval = --m_value; pthread_mutex_unlock(&m_mutex); return retval; }
311 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { pthread_mutex_lock(&m_mutex); int retval = m_value--; pthread_mutex_unlock(&m_mutex); return retval; }
312 __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; }
313 #endif
314 
315 
316 #endif // PTLIB_CRITICALSECTION_H
317 
318 
319 // End Of File ///////////////////////////////////////////////////////////////
friend __inline ostream & operator<<(ostream &strm, const PAtomicInteger &i)
Definition: critsec.h:204
int IntegerType
Definition: critsec.h:140
This class waits for the semaphore on construction and automatically signals the semaphore on destruc...
Definition: psync.h:86
virtual void Wait()=0
Block until the synchronisation object is available.
__inline bool operator!() const
Test if atomic integer has a non-zero value.
Definition: critsec.h:202
#define PCLASSINFO(cls, par)
Declare all the standard PTLib class information.
Definition: object.h:1049
pthread_mutex_t m_mutex
Definition: critsec.h:142
Definition: critsec.h:128
__inline PAtomicBoolean & operator=(bool value)
Assign a value to the atomic boolean.
Definition: critsec.h:257
Definition: psync.h:45
void SetValue(IntegerType value)
Set the value of the atomic integer.
Definition: critsec.h:189
PWaitAndSignal PEnterAndLeave
This class implements critical section mutexes using the most efficient mechanism available on the ho...
Definition: critsec.h:125
This class implements an atomic "test and set" boolean.
Definition: critsec.h:241
__inline PAtomicInteger & operator=(IntegerType value)
Assign a value to the atomic integer.
Definition: critsec.h:186
This class implements an integer that can be atomically incremented and decremented in a thread-safe ...
Definition: critsec.h:171
~PAtomicBase()
Destroy the atomic integer.
Definition: critsec.h:275
IntegerType m_value
Definition: critsec.h:146
__inline bool IsZero() const
Test if an atomic integer has a zero value.
Definition: critsec.h:199
IntegerType operator++()
atomically pre-increment the integer value
Definition: critsec.h:276
IntegerType operator--()
atomically pre-decrement the integer value
Definition: critsec.h:278
PAtomicBase(IntegerType value)
Definition: critsec.h:274
__inline bool operator!() const
Test if atomic integer has a non-zero value.
Definition: critsec.h:254
virtual void Signal()=0
Signal that the synchronisation object is available.
PAtomicInteger(IntegerType value=0)
Create a PAtomicInteger with the specified initial value.
Definition: critsec.h:178
PAtomicBoolean(bool value=false)
Create a PAtomicBoolean with the specified initial value.
Definition: critsec.h:246
bool TestAndSet(bool value)
Test Set the value of the atomic boolean.
Definition: critsec.h:280
#define PCriticalSection
Definition: mutex.h:115
virtual PObject * Clone() const
Create a copy of the class on the heap.
PAtomicBase::IntegerType IntegerType
Definition: critsec.h:174
Ultimate parent class for all objects in the class library.
Definition: object.h:1118
friend __inline ostream & operator<<(ostream &strm, const PAtomicBoolean &b)
Definition: critsec.h:266