PTLib  Version 2.12.9
 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 {
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  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 
135 
136 
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:
156 
157  explicit PAtomicBase(IntegerType value);
158 
159  public:
161  ~PAtomicBase();
162 };
163 
164 
165 
181 {
182  public:
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 
219 
225  IntegerType operator++(int);
226 
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 
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) { }
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 ///////////////////////////////////////////////////////////////