123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- // Copyright (C) 2000 Sean Cavanaugh
- // This file is licensed under the terms of the Lesser GNU Public License
- // (see LPGL.txt, or http://www.gnu.org/copyleft/lesser.txt)
- #ifndef ReferenceCounter_H__
- #define ReferenceCounter_H__
- #if _MSC_VER > 1000
- #pragma once
- #endif // _MSC_VER > 1000
- #ifdef _WIN32
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #endif
- #ifdef HAVE_SYS_ATOMIC_H
- #include <sys/atomic.h>
- #endif
- #ifdef HAVE_ASM_ATOMIC_H
- #include <asm/atomic.h>
- #endif
- /*!
- \author Sean Cavanaugh
- \email [email protected]
- \cvsauthor $Author: sean $
- \date $Date: 2000/09/11 20:28:24 $
- \version $Revision: 1.1 $
- \brief ReferenceCounter abstracts a reference counted integer with proper thread safe access
- The interface is not platform specific in any way, except the protected data
- is platform specific, as well as the implementation details
- */
- class ReferenceCounter
- {
- // Construction
- public:
- ReferenceCounter();
- ReferenceCounter(int InitialValue);
- virtual ~ReferenceCounter() {} // Should optimize to nothing except in the derived-class case
- ReferenceCounter(const ReferenceCounter& other) {copy(other);}
- ReferenceCounter& operator=(const ReferenceCounter& other) {copy(other); return *this;}
- public:
- // User functions
- inline int add(int amt);// increment the value by amt, returns the ORIGINAL value
- inline int sub(int amt);// increment the value by amt, returns the ORIGINAL value
- inline int inc();// increment the value, returns the NEW value
- inline int dec();// decrement the value, returns the NEW value
- inline int read() const;// read the current value
- inline void write(int newvalue);// change the counter to a new value blindly
- inline int swap(int newvalue);// change the counter to a new value, and return the ORIGINAL value
- // Convenient Operators
- int operator++() {return inc();}
- int operator--() {return dec();}
- int operator++(int) {return inc() - 1;}
- int operator--(int) {return dec() + 1;}
- int operator+=(int amt) {return add(amt) + amt;}
- int operator-=(int amt) {return sub(amt) - amt;}
- int operator=(int value) {write(value); return value;}
- operator int() const {return read();}
- // Internal Methods
- protected:
- inline void copy(const ReferenceCounter& other);
- // Data
- protected:
- #ifdef SINGLE_THREADED
- int m_atom;
- #else //SINGLE_THREADED
- #ifdef _WIN32
- long m_atom;
- #endif
- #ifdef HAVE_ATOMIC
- atomic_t m_atom;
- #endif
- #endif//SINGLE_THREADED
- };
- #ifdef SINGLE_THREADED
- inline ReferenceCounter::ReferenceCounter()
- {
- m_atom = 0;
- }
- inline ReferenceCounter::ReferenceCounter(int InitialValue)
- {
- m_atom = InitialValue;
- }
- inline int ReferenceCounter::add(int amt)
- {
- m_atom += amt;
- return m_atom;
- }
- inline int ReferenceCounter::sub(int amt)
- {
- m_atom -= amt;
- return m_atom;
- }
- inline int ReferenceCounter::inc()
- {
- m_atom++;
- return m_atom;
- }
- inline int ReferenceCounter::dec()
- {
- m_atom--;
- return m_atom;
- }
- inline int ReferenceCounter::swap(int newvalue)
- {
- int rval = m_atom;
- m_atom = newvalue;
- return rval;
- }
- inline void ReferenceCounter::write(int newvalue)
- {
- m_atom = newvalue;
- }
- inline int ReferenceCounter::read() const
- {
- return m_atom;
- }
- inline void ReferenceCounter::copy(const ReferenceCounter& other)
- {
- m_atom = other.m_atom;
- }
- #else // SINGLE_THREADED
- #ifdef _WIN32
- inline ReferenceCounter::ReferenceCounter()
- {
- m_atom = 0;
- }
- inline ReferenceCounter::ReferenceCounter(int InitialValue)
- {
- m_atom = InitialValue;
- }
- inline int ReferenceCounter::add(int amt)
- {
- return InterlockedExchangeAdd(&m_atom, amt);
- }
- inline int ReferenceCounter::sub(int amt)
- {
- return InterlockedExchangeAdd(&m_atom, -amt);
- }
- inline int ReferenceCounter::inc()
- {
- return InterlockedIncrement(&m_atom);
- }
- inline int ReferenceCounter::dec()
- {
- return InterlockedDecrement(&m_atom);
- }
- inline int ReferenceCounter::swap(int newvalue)
- {
- return InterlockedExchange(&m_atom, newvalue);
- }
- inline void ReferenceCounter::write(int newvalue)
- {
- InterlockedExchange(&m_atom, newvalue);
- }
- inline int ReferenceCounter::read() const
- {
- return m_atom;
- }
- inline void ReferenceCounter::copy(const ReferenceCounter& other)
- {
- m_atom = other.m_atom;
- }
- #endif//_WIN32
- #ifdef HAVE_ATOMIC
- inline ReferenceCounter::ReferenceCounter()
- {
- m_atom.counter = 0;
- }
- inline ReferenceCounter::ReferenceCounter(int InitialValue)
- {
- m_atom.counter = InitialValue;
- }
- inline int ReferenceCounter::add(int amt)
- {
- int rval = atomic_read(&m_atom);
- atomic_add(amt, &m_atom);
- return rval;
- }
- inline int ReferenceCounter::sub(int amt)
- {
- int rval = atomic_read(&m_atom);
- atomic_sub(amt, &m_atom);
- return rval;
- }
- inline int ReferenceCounter::inc()
- {
- int rval = atomic_read(&m_atom);
- atomic_inc(&m_atom);
- return rval + 1;
- }
- inline int ReferenceCounter::dec()
- {
- int rval = atomic_read(&m_atom);
- atomic_dec(&m_atom);
- return rval - 1;
- }
- inline int ReferenceCounter::swap(int newvalue)
- {
- int rval = atomic_read(&m_atom);
- atomic_set(&m_atom, newvalue);
- return rval;
- }
- inline void ReferenceCounter::write(int newvalue)
- {
- atomic_set(&m_atom, newvalue);
- }
- inline int ReferenceCounter::read() const
- {
- return atomic_read(&m_atom);
- }
- inline void ReferenceCounter::copy(const ReferenceCounter& other)
- {
- m_atom.counter = other.read();
- }
- #endif//HAVE_ATOMIC
- #endif//SINGLE_THREADED
- #endif//ReferenceCounter_H__
|