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 ///////////////////////////////////////////////////////////////

Generated on Fri Feb 15 20:58:31 2013 for PTLib by  doxygen 1.4.7