Atomic.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/StdTypes.h>
  7. #include <atomic>
  8. namespace anki
  9. {
  10. /// @addtogroup util_other
  11. /// @{
  12. enum class AtomicMemoryOrder
  13. {
  14. RELAXED = std::memory_order_relaxed,
  15. CONSUME = std::memory_order_consume,
  16. ACQUIRE = std::memory_order_acquire,
  17. RELEASE = std::memory_order_release,
  18. ACQ_REL = std::memory_order_acq_rel,
  19. SEQ_CST = std::memory_order_seq_cst
  20. };
  21. /// Atomic template. At the moment it doesn't work well with pointers.
  22. template<typename T, AtomicMemoryOrder tmemOrd = AtomicMemoryOrder::RELAXED>
  23. class Atomic
  24. {
  25. public:
  26. using Value = T;
  27. static constexpr AtomicMemoryOrder MEMORY_ORDER = tmemOrd;
  28. /// It will not set itself to zero.
  29. Atomic()
  30. {
  31. }
  32. Atomic(Value a)
  33. : m_val(a)
  34. {
  35. }
  36. Atomic(const Atomic&) = delete; // Non-copyable
  37. Atomic& operator=(const Atomic&) = delete; // Non-copyable
  38. /// Set the value without protection.
  39. void setNonAtomically(Value a)
  40. {
  41. m_val = a;
  42. }
  43. /// Get the value without protection.
  44. Value getNonAtomically() const
  45. {
  46. return m_val;
  47. }
  48. /// Get the value of the atomic.
  49. Value load(AtomicMemoryOrder memOrd = MEMORY_ORDER) const
  50. {
  51. return m_att.load(static_cast<std::memory_order>(memOrd));
  52. }
  53. /// Store
  54. void store(Value a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  55. {
  56. m_att.store(a, static_cast<std::memory_order>(memOrd));
  57. }
  58. /// Fetch and add.
  59. template<typename Y>
  60. Value fetchAdd(Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  61. {
  62. return m_att.fetch_add(a, static_cast<std::memory_order>(memOrd));
  63. }
  64. /// Fetch and subtract.
  65. template<typename Y>
  66. Value fetchSub(Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  67. {
  68. return m_att.fetch_sub(a, static_cast<std::memory_order>(memOrd));
  69. }
  70. /// Fetch and do bitwise or.
  71. template<typename Y>
  72. Value fetchOr(Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  73. {
  74. return m_att.fetch_or(a, static_cast<std::memory_order>(memOrd));
  75. }
  76. /// Fetch and do bitwise and.
  77. template<typename Y>
  78. Value fetchAnd(Y a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  79. {
  80. return m_att.fetch_and(a, static_cast<std::memory_order>(memOrd));
  81. }
  82. /// @code
  83. /// if(m_val == expected) {
  84. /// m_val = desired;
  85. /// return true;
  86. /// } else {
  87. /// expected = m_val;
  88. /// return false;
  89. /// }
  90. /// @endcode
  91. Bool compareExchange(Value& expected, Value desired, AtomicMemoryOrder successMemOrd = MEMORY_ORDER,
  92. AtomicMemoryOrder failMemOrd = MEMORY_ORDER)
  93. {
  94. return m_att.compare_exchange_weak(expected, desired, static_cast<std::memory_order>(successMemOrd),
  95. static_cast<std::memory_order>(failMemOrd));
  96. }
  97. /// Set @a a to the atomic and return the previous value.
  98. Value exchange(Value a, AtomicMemoryOrder memOrd = MEMORY_ORDER)
  99. {
  100. return m_att.exchange(a, static_cast<std::memory_order>(memOrd));
  101. }
  102. /// Store the minimum using compare-and-swap.
  103. void min(Value a)
  104. {
  105. Value prev = load();
  106. while(a < prev && !compareExchange(prev, a))
  107. {
  108. }
  109. }
  110. /// Store the maximum using compare-and-swap.
  111. void max(Value a)
  112. {
  113. Value prev = load();
  114. while(a > prev && !compareExchange(prev, a))
  115. {
  116. }
  117. }
  118. private:
  119. union
  120. {
  121. Value m_val;
  122. std::atomic<Value> m_att;
  123. };
  124. };
  125. /// @}
  126. } // end namespace anki