00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef PTLIB_CRITICALSECTION_H
00032 #define PTLIB_CRITICALSECTION_H
00033
00034 #include <ptlib/psync.h>
00035
00036 #if defined(SOLARIS) && !defined(__GNUC__)
00037 #include <atomic.h>
00038 #endif
00039
00040 #if P_HAS_ATOMIC_INT
00041
00042 #if defined(__GNUC__)
00043 # if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
00044 # include <ext/atomicity.h>
00045 # else
00046 # include <bits/atomicity.h>
00047 # endif
00048 #endif
00049
00050 #if P_NEEDS_GNU_CXX_NAMESPACE
00051 #define EXCHANGE_AND_ADD(v,i) __gnu_cxx::__exchange_and_add(v,i)
00052 #else
00053 #define EXCHANGE_AND_ADD(v,i) __exchange_and_add(v,i)
00054 #endif
00055
00056 #endif // P_HAS_ATOMIC_INT
00057
00058
00065 #ifdef _WIN32
00066
00067 class PCriticalSection : public PSync
00068 {
00069 PCLASSINFO(PCriticalSection, PSync);
00070
00071 public:
00076 PCriticalSection();
00077
00081 PCriticalSection(const PCriticalSection &);
00082
00085 ~PCriticalSection();
00086
00090 PCriticalSection & operator=(const PCriticalSection &) { return *this; }
00092
00097 PObject * Clone() const
00098 {
00099 return new PCriticalSection();
00100 }
00101
00104 void Wait();
00105 inline void Enter() { Wait(); }
00106
00109 void Signal();
00110 inline void Leave() { Signal(); }
00111
00115 bool Try();
00117
00118
00119 #include "msos/ptlib/critsec.h"
00120
00121 };
00122
00123 #endif
00124
00125 typedef PWaitAndSignal PEnterAndLeave;
00126
00127
00128 class PAtomicBase
00129 {
00130 public:
00131 #if defined(_WIN32)
00132 typedef long IntegerType;
00133 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
00134 typedef __stl_atomic_t IntegerType;
00135 #elif defined(SOLARIS) && !defined(__GNUC__)
00136 typedef uint32_t IntegerType;
00137 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
00138 typedef _Atomic_word IntegerType;
00139 #else
00140 typedef int IntegerType;
00141 protected:
00142 pthread_mutex_t m_mutex;
00143 #endif
00144
00145 protected:
00146 IntegerType m_value;
00147
00148 explicit PAtomicBase(IntegerType value);
00149
00150 public:
00152 ~PAtomicBase();
00153 };
00154
00155
00156
00171 class PAtomicInteger : PAtomicBase
00172 {
00173 public:
00174 typedef PAtomicBase::IntegerType IntegerType;
00175
00178 explicit PAtomicInteger(
00179 IntegerType value = 0
00180 ) : PAtomicBase(value) { }
00181
00183 __inline operator IntegerType() const { return m_value; }
00184
00186 __inline PAtomicInteger & operator=(IntegerType value) { m_value = value; return *this; }
00187
00189 void SetValue(
00190 IntegerType value
00191 ) { m_value = value; }
00192
00199 __inline bool IsZero() const { return m_value == 0; }
00200
00202 __inline bool operator!() const { return m_value != 0; }
00203
00204 friend __inline ostream & operator<<(ostream & strm, const PAtomicInteger & i)
00205 {
00206 return strm << i.m_value;
00207 }
00208
00214 IntegerType operator++();
00215
00221 IntegerType operator++(int);
00222
00228 IntegerType operator--();
00229
00235 IntegerType operator--(int);
00236 };
00237
00238
00241 class PAtomicBoolean : PAtomicBase
00242 {
00243 public:
00246 explicit PAtomicBoolean(
00247 bool value = false
00248 ) : PAtomicBase(value ? 1 : 0) { }
00249
00251 __inline operator bool() const { return m_value != 0; }
00252
00254 __inline bool operator!() const { return m_value != 0; }
00255
00257 __inline PAtomicBoolean & operator=(bool value) { m_value = value ? 1 : 0; return *this; }
00258
00262 bool TestAndSet(
00263 bool value
00264 );
00265
00266 friend __inline ostream & operator<<(ostream & strm, const PAtomicBoolean & b)
00267 {
00268 return strm << (b.m_value != 0 ? "true" : "false");
00269 }
00270 };
00271
00272
00273 #if defined(_WIN32) || defined(DOC_PLUS_PLUS)
00274 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
00275 __inline PAtomicBase::~PAtomicBase() { }
00276 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return InterlockedIncrement (&m_value); }
00277 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return InterlockedExchangeAdd(&m_value, 1); }
00278 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return InterlockedDecrement (&m_value); }
00279 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return InterlockedExchangeAdd(&m_value, -1); }
00280 __inline bool PAtomicBoolean::TestAndSet(bool value) { return InterlockedExchange (&m_value, value) != 0; }
00281 #elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
00282 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
00283 __inline PAtomicBase::~PAtomicBase() { }
00284 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return _STLP_ATOMIC_INCREMENT(&m_value); }
00285 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return _STLP_ATOMIC_INCREMENT(&m_value)-1; }
00286 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return _STLP_ATOMIC_DECREMENT(&m_value); }
00287 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return _STLP_ATOMIC_DECREMENT(&m_value)+1; }
00288 __inline bool PAtomicBoolean::TestAndSet(bool value) { return _STLP_ATOMIC_EXCHANGE (&m_value, value) != 0; }
00289 #elif defined(SOLARIS) && !defined(__GNUC__)
00290 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
00291 __inline PAtomicBase::~PAtomicBase() { }
00292 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return atomic_add_32_nv(&m_value, 1); }
00293 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return atomic_add_32_nv(&m_value, 1)-1; }
00294 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return atomic_add_32_nv(&m_value, -1); }
00295 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return atomic_add_32_nv(&m_value, -1)+1; }
00296 __inline bool PAtomicBoolean::TestAndSet(bool value) { return atomic_swap_32 (&m_value, value) != 0; }
00297 #elif defined(__GNUC__) && P_HAS_ATOMIC_INT
00298 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
00299 __inline PAtomicBase::~PAtomicBase() { }
00300 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return EXCHANGE_AND_ADD(&m_value, 1)+1; }
00301 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return EXCHANGE_AND_ADD(&m_value, 1); }
00302 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return EXCHANGE_AND_ADD(&m_value, -1)-1; }
00303 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return EXCHANGE_AND_ADD(&m_value, -1); }
00304 __inline bool PAtomicBoolean::TestAndSet(bool value) { IntegerType previous = EXCHANGE_AND_ADD(&m_value, value?1:-1); m_value = value?1:0; return previous > 0; }
00305 #else
00306 __inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { pthread_mutex_init(&m_mutex, NULL); }
00307 __inline PAtomicBase::~PAtomicBase() { pthread_mutex_destroy(&m_mutex); }
00308 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { pthread_mutex_lock(&m_mutex); int retval = ++m_value; pthread_mutex_unlock(&m_mutex); return retval; }
00309 __inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { pthread_mutex_lock(&m_mutex); int retval = m_value++; pthread_mutex_unlock(&m_mutex); return retval; }
00310 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { pthread_mutex_lock(&m_mutex); int retval = --m_value; pthread_mutex_unlock(&m_mutex); return retval; }
00311 __inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { pthread_mutex_lock(&m_mutex); int retval = m_value--; pthread_mutex_unlock(&m_mutex); return retval; }
00312 __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; }
00313 #endif
00314
00315
00316 #endif // PTLIB_CRITICALSECTION_H
00317
00318
00319