Atomic.h 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #ifndef ANKI_UTIL_ATOMIC_H
  6. #define ANKI_UTIL_ATOMIC_H
  7. #include "anki/util/StdTypes.h"
  8. #include "anki/util/NonCopyable.h"
  9. namespace anki {
  10. /// @addtogroup util_other
  11. /// @{
  12. enum class AtomicMemoryOrder
  13. {
  14. #if defined(__GNUC__)
  15. RELAXED = __ATOMIC_RELAXED,
  16. CONSUME = __ATOMIC_CONSUME,
  17. ACQUIRE = __ATOMIC_ACQUIRE,
  18. RELEASE = __ATOMIC_RELEASE,
  19. ACQ_REL = __ATOMIC_ACQ_REL,
  20. SEQ_CST = __ATOMIC_SEQ_CST
  21. #else
  22. # error "TODO"
  23. #endif
  24. };
  25. /// Atomic template.
  26. template<typename T, AtomicMemoryOrder tmemOrd = AtomicMemoryOrder::RELAXED>
  27. class Atomic: public NonCopyable
  28. {
  29. public:
  30. using Value = T;
  31. static constexpr AtomicMemoryOrder MEMORY_ORDER = tmemOrd;
  32. Atomic()
  33. : m_val(static_cast<Value>(0))
  34. {}
  35. Atomic(const Value a)
  36. : m_val(a)
  37. {}
  38. Value load(AtomicMemoryOrder memOrd = MEMORY_ORDER) const
  39. {
  40. #if defined(__GNUC__)
  41. return __atomic_load_n(&m_val, static_cast<int>(memOrd));
  42. #else
  43. # error "TODO"
  44. #endif
  45. }
  46. void store(const Value a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  47. {
  48. #if defined(__GNUC__)
  49. __atomic_store_n(&m_val, a, static_cast<int>(memOrd));
  50. #else
  51. # error "TODO"
  52. #endif
  53. }
  54. template<typename Y>
  55. Value fetchAdd(const Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  56. {
  57. #if defined(__GNUC__)
  58. return __atomic_fetch_add(&m_val, a, static_cast<int>(memOrd));
  59. #else
  60. # error "TODO"
  61. #endif
  62. }
  63. template<typename Y>
  64. Value fetchSub(const Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  65. {
  66. #if defined(__GNUC__)
  67. return __atomic_fetch_sub(&m_val, a, static_cast<int>(memOrd));
  68. #else
  69. # error "TODO"
  70. #endif
  71. }
  72. /// @code
  73. /// if(m_val == expected) {
  74. /// m_val = desired;
  75. /// return true;
  76. /// } else {
  77. /// expected = m_val;
  78. /// return false;
  79. /// }
  80. /// @endcode
  81. Bool compareExchange(Value& expected, const Value desired,
  82. AtomicMemoryOrder memOrd = MEMORY_ORDER)
  83. {
  84. #if defined(__GNUC__)
  85. return __atomic_compare_exchange_n(&m_val, &expected, desired,
  86. false, static_cast<int>(memOrd), __ATOMIC_RELAXED);
  87. #else
  88. # error "TODO"
  89. #endif
  90. }
  91. /// Set @a a to the atomic and return the previous value.
  92. Value exchange(const Value a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  93. {
  94. #if defined(__GNUC__)
  95. return __atomic_exchange_n(&m_val, a, static_cast<int>(memOrd));
  96. #else
  97. # error "TODO"
  98. #endif
  99. }
  100. private:
  101. Value m_val;
  102. };
  103. /// @}
  104. } // end namespace anki
  105. #endif