All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
critsec.h
Go to the documentation of this file.
/*
* critsec.h
*
* Critical section mutex class.
*
* Portable Windows Library
*
* Copyright (C) 2004 Post Increment
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Post Increment
*
* Contributor(s): ______________________________________.
*
* $Revision: 29078 $
* $Author: rjongbloed $
* $Date: 2013-02-12 17:22:50 -0600 (Tue, 12 Feb 2013) $
*/
#ifndef PTLIB_CRITICALSECTION_H
#define PTLIB_CRITICALSECTION_H
#include <ptlib/psync.h>
#if defined(SOLARIS) && !defined(__GNUC__)
#include <atomic.h>
#endif
#if P_HAS_ATOMIC_INT
#if defined(__GNUC__)
# if __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
# include <ext/atomicity.h>
# else
# include <bits/atomicity.h>
# endif
#endif
#if P_NEEDS_GNU_CXX_NAMESPACE
#define EXCHANGE_AND_ADD(v,i) __gnu_cxx::__exchange_and_add(v,i)
#else
#define EXCHANGE_AND_ADD(v,i) __exchange_and_add(v,i)
#endif
#endif // P_HAS_ATOMIC_INT
#ifdef _WIN32
class PCriticalSection : public PSync
{
PCLASSINFO(PCriticalSection, PSync);
public:
PCriticalSection();
PCriticalSection(const PCriticalSection &);
~PCriticalSection();
PCriticalSection & operator=(const PCriticalSection &) { return *this; }
PObject * Clone() const
{
return new PCriticalSection();
}
void Wait();
inline void Enter() { Wait(); }
void Signal();
inline void Leave() { Signal(); }
bool Try();
#include "msos/ptlib/critsec.h"
};
#endif
typedef PWaitAndSignal PEnterAndLeave;
class PAtomicBase
{
public:
#if defined(_WIN32)
typedef long IntegerType;
#elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
typedef __stl_atomic_t IntegerType;
#elif defined(SOLARIS) && !defined(__GNUC__)
typedef uint32_t IntegerType;
#elif defined(__GNUC__) && P_HAS_ATOMIC_INT
typedef _Atomic_word IntegerType;
#else
typedef int IntegerType;
protected:
pthread_mutex_t m_mutex;
#endif
protected:
IntegerType m_value;
explicit PAtomicBase(IntegerType value);
public:
~PAtomicBase();
};
class PAtomicInteger : PAtomicBase
{
public:
typedef PAtomicBase::IntegerType IntegerType;
explicit PAtomicInteger(
IntegerType value = 0
) : PAtomicBase(value) { }
__inline operator IntegerType() const { return m_value; }
__inline PAtomicInteger & operator=(IntegerType value) { m_value = value; return *this; }
void SetValue(
IntegerType value
) { m_value = value; }
__inline bool IsZero() const { return m_value == 0; }
__inline bool operator!() const { return m_value != 0; }
friend __inline ostream & operator<<(ostream & strm, const PAtomicInteger & i)
{
return strm << i.m_value;
}
IntegerType operator++();
IntegerType operator++(int);
IntegerType operator--();
IntegerType operator--(int);
};
class PAtomicBoolean : PAtomicBase
{
public:
explicit PAtomicBoolean(
bool value = false
) : PAtomicBase(value ? 1 : 0) { }
__inline operator bool() const { return m_value != 0; }
__inline bool operator!() const { return m_value != 0; }
__inline PAtomicBoolean & operator=(bool value) { m_value = value ? 1 : 0; return *this; }
bool TestAndSet(
bool value
);
friend __inline ostream & operator<<(ostream & strm, const PAtomicBoolean & b)
{
return strm << (b.m_value != 0 ? "true" : "false");
}
};
#if defined(_WIN32) || defined(DOC_PLUS_PLUS)
__inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
__inline PAtomicBase::~PAtomicBase() { }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return InterlockedIncrement (&m_value); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return InterlockedExchangeAdd(&m_value, 1); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return InterlockedDecrement (&m_value); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return InterlockedExchangeAdd(&m_value, -1); }
__inline bool PAtomicBoolean::TestAndSet(bool value) { return InterlockedExchange (&m_value, value) != 0; }
#elif defined(_STLP_INTERNAL_THREADS_H) && defined(_STLP_ATOMIC_INCREMENT) && defined(_STLP_ATOMIC_DECREMENT)
__inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
__inline PAtomicBase::~PAtomicBase() { }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return _STLP_ATOMIC_INCREMENT(&m_value); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return _STLP_ATOMIC_INCREMENT(&m_value)-1; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return _STLP_ATOMIC_DECREMENT(&m_value); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return _STLP_ATOMIC_DECREMENT(&m_value)+1; }
__inline bool PAtomicBoolean::TestAndSet(bool value) { return _STLP_ATOMIC_EXCHANGE (&m_value, value) != 0; }
#elif defined(SOLARIS) && !defined(__GNUC__)
__inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
__inline PAtomicBase::~PAtomicBase() { }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return atomic_add_32_nv(&m_value, 1); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return atomic_add_32_nv(&m_value, 1)-1; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return atomic_add_32_nv(&m_value, -1); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return atomic_add_32_nv(&m_value, -1)+1; }
__inline bool PAtomicBoolean::TestAndSet(bool value) { return atomic_swap_32 (&m_value, value) != 0; }
#elif defined(__GNUC__) && P_HAS_ATOMIC_INT
__inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { }
__inline PAtomicBase::~PAtomicBase() { }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { return EXCHANGE_AND_ADD(&m_value, 1)+1; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { return EXCHANGE_AND_ADD(&m_value, 1); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { return EXCHANGE_AND_ADD(&m_value, -1)-1; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { return EXCHANGE_AND_ADD(&m_value, -1); }
__inline bool PAtomicBoolean::TestAndSet(bool value) { IntegerType previous = EXCHANGE_AND_ADD(&m_value, value?1:-1); m_value = value?1:0; return previous > 0; }
#else
__inline PAtomicBase::PAtomicBase(IntegerType value) : m_value(value) { pthread_mutex_init(&m_mutex, NULL); }
__inline PAtomicBase::~PAtomicBase() { pthread_mutex_destroy(&m_mutex); }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++() { pthread_mutex_lock(&m_mutex); int retval = ++m_value; pthread_mutex_unlock(&m_mutex); return retval; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator++(int) { pthread_mutex_lock(&m_mutex); int retval = m_value++; pthread_mutex_unlock(&m_mutex); return retval; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--() { pthread_mutex_lock(&m_mutex); int retval = --m_value; pthread_mutex_unlock(&m_mutex); return retval; }
__inline PAtomicInteger::IntegerType PAtomicInteger::operator--(int) { pthread_mutex_lock(&m_mutex); int retval = m_value--; pthread_mutex_unlock(&m_mutex); return retval; }
__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; }
#endif
#endif // PTLIB_CRITICALSECTION_H
// End Of File ///////////////////////////////////////////////////////////////
PAtomicInteger::operator<<
friend __inline ostream & operator<<(ostream &strm, const PAtomicInteger &i)
Definition: critsec.h:204
PAtomicBase::IntegerType
int IntegerType
Definition: critsec.h:140
PWaitAndSignal
This class waits for the semaphore on construction and automatically signals the semaphore on destruc...
Definition: psync.h:86
PSync::Wait
virtual void Wait()=0
Block until the synchronisation object is available.
PAtomicInteger::operator!
__inline bool operator!() const
Test if atomic integer has a non-zero value.
Definition: critsec.h:202
PCLASSINFO
#define PCLASSINFO(cls, par)
Declare all the standard PTLib class information.
Definition: object.h:1049
PAtomicBase::m_mutex
pthread_mutex_t m_mutex
Definition: critsec.h:142
PAtomicBase
Definition: critsec.h:128
PAtomicBoolean::operator=
__inline PAtomicBoolean & operator=(bool value)
Assign a value to the atomic boolean.
Definition: critsec.h:257
PSync
Definition: psync.h:45
PAtomicInteger::SetValue
void SetValue(IntegerType value)
Set the value of the atomic integer.
Definition: critsec.h:189
PEnterAndLeave
PWaitAndSignal PEnterAndLeave
This class implements critical section mutexes using the most efficient mechanism available on the ho...
Definition: critsec.h:125
PAtomicBoolean
This class implements an atomic "test and set" boolean.
Definition: critsec.h:241
PAtomicInteger::operator=
__inline PAtomicInteger & operator=(IntegerType value)
Assign a value to the atomic integer.
Definition: critsec.h:186
PAtomicInteger
This class implements an integer that can be atomically incremented and decremented in a thread-safe ...
Definition: critsec.h:171
PAtomicBase::~PAtomicBase
~PAtomicBase()
Destroy the atomic integer.
Definition: critsec.h:275
PAtomicBase::m_value
IntegerType m_value
Definition: critsec.h:146
PAtomicInteger::IsZero
__inline bool IsZero() const
Test if an atomic integer has a zero value.
Definition: critsec.h:199
PAtomicInteger::operator++
IntegerType operator++()
atomically pre-increment the integer value
Definition: critsec.h:276
PAtomicInteger::operator--
IntegerType operator--()
atomically pre-decrement the integer value
Definition: critsec.h:278
PAtomicBase::PAtomicBase
PAtomicBase(IntegerType value)
Definition: critsec.h:274
PAtomicBoolean::operator!
__inline bool operator!() const
Test if atomic integer has a non-zero value.
Definition: critsec.h:254
PSync::Signal
virtual void Signal()=0
Signal that the synchronisation object is available.
PAtomicInteger::PAtomicInteger
PAtomicInteger(IntegerType value=0)
Create a PAtomicInteger with the specified initial value.
Definition: critsec.h:178
PAtomicBoolean::PAtomicBoolean
PAtomicBoolean(bool value=false)
Create a PAtomicBoolean with the specified initial value.
Definition: critsec.h:246
PAtomicBoolean::TestAndSet
bool TestAndSet(bool value)
Test Set the value of the atomic boolean.
Definition: critsec.h:280
psync.h
PCriticalSection
#define PCriticalSection
Definition: mutex.h:115
PObject::Clone
virtual PObject * Clone() const
Create a copy of the class on the heap.
PAtomicInteger::IntegerType
PAtomicBase::IntegerType IntegerType
Definition: critsec.h:174
PObject
Ultimate parent class for all objects in the class library.
Definition: object.h:1118
PAtomicBoolean::operator<<
friend __inline ostream & operator<<(ostream &strm, const PAtomicBoolean &b)
Definition: critsec.h:266