ReferenceCounter.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright (C) 2000 Sean Cavanaugh
  2. // This file is licensed under the terms of the Lesser GNU Public License
  3. // (see LPGL.txt, or http://www.gnu.org/copyleft/lesser.txt)
  4. #ifndef ReferenceCounter_H__
  5. #define ReferenceCounter_H__
  6. #if _MSC_VER > 1000
  7. #pragma once
  8. #endif // _MSC_VER > 1000
  9. #ifdef _WIN32
  10. #define WIN32_LEAN_AND_MEAN
  11. #include <windows.h>
  12. #endif
  13. #ifdef HAVE_SYS_ATOMIC_H
  14. #include <sys/atomic.h>
  15. #endif
  16. #ifdef HAVE_ASM_ATOMIC_H
  17. #include <asm/atomic.h>
  18. #endif
  19. /*!
  20. \author Sean Cavanaugh
  21. \email [email protected]
  22. \cvsauthor $Author: sean $
  23. \date $Date: 2000/09/11 20:28:24 $
  24. \version $Revision: 1.1 $
  25. \brief ReferenceCounter abstracts a reference counted integer with proper thread safe access
  26. The interface is not platform specific in any way, except the protected data
  27. is platform specific, as well as the implementation details
  28. */
  29. class ReferenceCounter
  30. {
  31. // Construction
  32. public:
  33. ReferenceCounter();
  34. ReferenceCounter(int InitialValue);
  35. virtual ~ReferenceCounter() {} // Should optimize to nothing except in the derived-class case
  36. ReferenceCounter(const ReferenceCounter& other) {copy(other);}
  37. ReferenceCounter& operator=(const ReferenceCounter& other) {copy(other); return *this;}
  38. public:
  39. // User functions
  40. inline int add(int amt);// increment the value by amt, returns the ORIGINAL value
  41. inline int sub(int amt);// increment the value by amt, returns the ORIGINAL value
  42. inline int inc();// increment the value, returns the NEW value
  43. inline int dec();// decrement the value, returns the NEW value
  44. inline int read() const;// read the current value
  45. inline void write(int newvalue);// change the counter to a new value blindly
  46. inline int swap(int newvalue);// change the counter to a new value, and return the ORIGINAL value
  47. // Convenient Operators
  48. int operator++() {return inc();}
  49. int operator--() {return dec();}
  50. int operator++(int) {return inc() - 1;}
  51. int operator--(int) {return dec() + 1;}
  52. int operator+=(int amt) {return add(amt) + amt;}
  53. int operator-=(int amt) {return sub(amt) - amt;}
  54. int operator=(int value) {write(value); return value;}
  55. operator int() const {return read();}
  56. // Internal Methods
  57. protected:
  58. inline void copy(const ReferenceCounter& other);
  59. // Data
  60. protected:
  61. #ifdef SINGLE_THREADED
  62. int m_atom;
  63. #else //SINGLE_THREADED
  64. #ifdef _WIN32
  65. long m_atom;
  66. #endif
  67. #ifdef HAVE_ATOMIC
  68. atomic_t m_atom;
  69. #endif
  70. #endif//SINGLE_THREADED
  71. };
  72. #ifdef SINGLE_THREADED
  73. inline ReferenceCounter::ReferenceCounter()
  74. {
  75. m_atom = 0;
  76. }
  77. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  78. {
  79. m_atom = InitialValue;
  80. }
  81. inline int ReferenceCounter::add(int amt)
  82. {
  83. m_atom += amt;
  84. return m_atom;
  85. }
  86. inline int ReferenceCounter::sub(int amt)
  87. {
  88. m_atom -= amt;
  89. return m_atom;
  90. }
  91. inline int ReferenceCounter::inc()
  92. {
  93. m_atom++;
  94. return m_atom;
  95. }
  96. inline int ReferenceCounter::dec()
  97. {
  98. m_atom--;
  99. return m_atom;
  100. }
  101. inline int ReferenceCounter::swap(int newvalue)
  102. {
  103. int rval = m_atom;
  104. m_atom = newvalue;
  105. return rval;
  106. }
  107. inline void ReferenceCounter::write(int newvalue)
  108. {
  109. m_atom = newvalue;
  110. }
  111. inline int ReferenceCounter::read() const
  112. {
  113. return m_atom;
  114. }
  115. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  116. {
  117. m_atom = other.m_atom;
  118. }
  119. #else // SINGLE_THREADED
  120. #ifdef _WIN32
  121. inline ReferenceCounter::ReferenceCounter()
  122. {
  123. m_atom = 0;
  124. }
  125. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  126. {
  127. m_atom = InitialValue;
  128. }
  129. inline int ReferenceCounter::add(int amt)
  130. {
  131. return InterlockedExchangeAdd(&m_atom, amt);
  132. }
  133. inline int ReferenceCounter::sub(int amt)
  134. {
  135. return InterlockedExchangeAdd(&m_atom, -amt);
  136. }
  137. inline int ReferenceCounter::inc()
  138. {
  139. return InterlockedIncrement(&m_atom);
  140. }
  141. inline int ReferenceCounter::dec()
  142. {
  143. return InterlockedDecrement(&m_atom);
  144. }
  145. inline int ReferenceCounter::swap(int newvalue)
  146. {
  147. return InterlockedExchange(&m_atom, newvalue);
  148. }
  149. inline void ReferenceCounter::write(int newvalue)
  150. {
  151. InterlockedExchange(&m_atom, newvalue);
  152. }
  153. inline int ReferenceCounter::read() const
  154. {
  155. return m_atom;
  156. }
  157. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  158. {
  159. m_atom = other.m_atom;
  160. }
  161. #endif//_WIN32
  162. #ifdef HAVE_ATOMIC
  163. inline ReferenceCounter::ReferenceCounter()
  164. {
  165. m_atom.counter = 0;
  166. }
  167. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  168. {
  169. m_atom.counter = InitialValue;
  170. }
  171. inline int ReferenceCounter::add(int amt)
  172. {
  173. int rval = atomic_read(&m_atom);
  174. atomic_add(amt, &m_atom);
  175. return rval;
  176. }
  177. inline int ReferenceCounter::sub(int amt)
  178. {
  179. int rval = atomic_read(&m_atom);
  180. atomic_sub(amt, &m_atom);
  181. return rval;
  182. }
  183. inline int ReferenceCounter::inc()
  184. {
  185. int rval = atomic_read(&m_atom);
  186. atomic_inc(&m_atom);
  187. return rval + 1;
  188. }
  189. inline int ReferenceCounter::dec()
  190. {
  191. int rval = atomic_read(&m_atom);
  192. atomic_dec(&m_atom);
  193. return rval - 1;
  194. }
  195. inline int ReferenceCounter::swap(int newvalue)
  196. {
  197. int rval = atomic_read(&m_atom);
  198. atomic_set(&m_atom, newvalue);
  199. return rval;
  200. }
  201. inline void ReferenceCounter::write(int newvalue)
  202. {
  203. atomic_set(&m_atom, newvalue);
  204. }
  205. inline int ReferenceCounter::read() const
  206. {
  207. return atomic_read(&m_atom);
  208. }
  209. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  210. {
  211. m_atom.counter = other.read();
  212. }
  213. #endif//HAVE_ATOMIC
  214. #endif//SINGLE_THREADED
  215. #endif//ReferenceCounter_H__