/sparrowhawk/foundation/ESFSharedCounter.h

http://github.com/jtblatt/duderino · C Header · 157 lines · 93 code · 36 blank · 28 comment · 1 complexity · f4db596c085c5b474fdcb34f2a711a06 MD5 · raw file

  1. /** @file ESFSharedCounter.h
  2. * @brief A threadsafe counter
  3. *
  4. * Copyright (c) 2011 Yahoo! Inc.
  5. * The copyrights embodied in the content of this file are licensed by Yahoo! Inc.
  6. * under the BSD (revised) open source license.
  7. *
  8. * Derived from code that is Copyright (c) 2009 Joshua Blatt and offered under both
  9. * BSD and Apache 2.0 licenses (http://sourceforge.net/projects/sparrowhawk/).
  10. *
  11. * $Author: blattj $
  12. * $Date: 2009/05/25 21:51:08 $
  13. * $Name: $
  14. * $Revision: 1.3 $
  15. */
  16. #ifndef ESF_SHARED_COUNTER_H
  17. #define ESF_SHARED_COUNTER_H
  18. #ifndef ESF_CONFIG_H
  19. #include <ESFConfig.h>
  20. #endif
  21. #ifndef ESF_ALLOCATOR_H
  22. #include <ESFAllocator.h>
  23. #endif
  24. #ifndef HAVE_X86_ASM
  25. #ifndef ESF_MUTEX_H
  26. #include <ESFMutex.h>
  27. #endif
  28. #endif
  29. /** @defgroup counter Counters */
  30. /** ESFSharedCounter is an integer type that can be safely accessed by
  31. * multiple threads.
  32. *
  33. * @ingroup counter
  34. */
  35. class ESFSharedCounter {
  36. public:
  37. /** Default constructor. */
  38. ESFSharedCounter();
  39. ESFSharedCounter(ESFSharedCounter &counter);
  40. virtual ~ESFSharedCounter();
  41. ESFSharedCounter &operator=(ESFSharedCounter &counter);
  42. inline void set(int value) {
  43. _counter = value;
  44. }
  45. inline int get() const {
  46. return _counter;
  47. }
  48. inline int inc() {
  49. unsigned int counter = 0;
  50. #ifdef HAVE_X86_ASM
  51. __asm__ __volatile__("lock; incl %0; movl %0, %1"
  52. :"=m" (_counter), "=r" (counter)
  53. :"m" (_counter)
  54. : "memory");
  55. #else
  56. _lock.writeAcquire();
  57. counter = _counter++;
  58. _lock.writeRelease();
  59. #endif
  60. return counter;
  61. }
  62. inline int dec() {
  63. unsigned int counter = 0;
  64. #ifdef HAVE_X86_ASM
  65. __asm__ __volatile__("lock; decl %0; movl %0, %1"
  66. :"=m" (_counter), "=r" (counter)
  67. :"m" (_counter)
  68. : "memory");
  69. #else
  70. _lock.writeAcquire();
  71. counter = _counter--;
  72. _lock.writeRelease();
  73. #endif
  74. return counter;
  75. }
  76. inline void add(int value) {
  77. #ifdef HAVE_X86_ASM
  78. __asm__ __volatile__("lock ; addl %1,%0"
  79. :"=m" (_counter)
  80. :"ir" (value), "m" (_counter));
  81. #else
  82. _lock.writeAcquire();
  83. _counter += value;
  84. _lock.writeRelease();
  85. #endif
  86. }
  87. inline void sub(int value) {
  88. #ifdef HAVE_X86_ASM
  89. __asm__ __volatile__("lock ; subl %1,%0"
  90. :"=m" (_counter)
  91. :"ir" (value), "m" (_counter));
  92. #else
  93. _lock.writeAcquire();
  94. _counter -= value;
  95. _lock.writeRelease();
  96. #endif
  97. }
  98. inline bool decAndTest() {
  99. unsigned char c;
  100. __asm__ __volatile__("lock ; decl %0; sete %1"
  101. :"=m" (_counter), "=qm" (c)
  102. :"m" (_counter)
  103. : "memory");
  104. return c != 0;
  105. }
  106. /** Placement new.
  107. *
  108. * @param size The size of the object.
  109. * @param allocator The source of the object's memory.
  110. * @return The new object or NULL of the memory allocation failed.
  111. */
  112. inline void *operator new(size_t size, ESFAllocator *allocator) {
  113. return allocator->allocate(size);
  114. }
  115. private:
  116. #ifndef HAVE_X86_ASM
  117. ESFMutex _lock;
  118. #endif
  119. volatile int _counter;
  120. };
  121. #endif /* ! ESF_SHARED_COUNTER_H */