# critsec.h

Go to the documentation of this file.

    00001 /*
    00002  * critsec.h
    00003  *
    00004  * Critical section mutex class.
    00005  *
    00006  * Portable Windows Library
    00007  *
    00008  * Copyright (C) 2004 Post Increment
    00009  *
    00010  * The contents of this file are subject to the Mozilla Public License
    00011  * Version 1.0 (the "License"); you may not use this file except in
    00012  * compliance with the License. You may obtain a copy of the License at
    00013  * http://www.mozilla.org/MPL/
    00014  *
    00015  * Software distributed under the License is distributed on an "AS IS"
    00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
    00017  * the License for the specific language governing rights and limitations
    00018  * under the License.
    00019  *
    00020  * The Original Code is Portable Windows Library.
    00021  *
    00022  * The Initial Developer of the Original Code is Post Increment
    00023  *
    00024  * Contributor(s): ______________________________________.
    00025  *
    00026  * $Revision: 29078 $
    00027  * $Author: rjongbloed $
    00028  * $Date: 2013-02-12 17:22:50 -0600 (Tue, 12 Feb 2013) $
    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 // End Of File ///////////////////////////////////////////////////////////////