atomic_ops.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #pragma once
  2. #include "atomic.h"
  3. #include <util/generic/typetraits.h>
  4. template <typename T>
  5. inline TAtomic* AsAtomicPtr(T volatile* target) {
  6. return reinterpret_cast<TAtomic*>(target);
  7. }
  8. template <typename T>
  9. inline const TAtomic* AsAtomicPtr(T const volatile* target) {
  10. return reinterpret_cast<const TAtomic*>(target);
  11. }
  12. // integral types
  13. template <typename T>
  14. struct TAtomicTraits {
  15. enum {
  16. Castable = std::is_integral<T>::value && sizeof(T) == sizeof(TAtomicBase) && !std::is_const<T>::value,
  17. };
  18. };
  19. template <typename T, typename TT>
  20. using TEnableIfCastable = std::enable_if_t<TAtomicTraits<T>::Castable, TT>;
  21. template <typename T>
  22. inline TEnableIfCastable<T, T> AtomicGet(T const volatile& target) {
  23. return static_cast<T>(AtomicGet(*AsAtomicPtr(&target)));
  24. }
  25. template <typename T>
  26. inline TEnableIfCastable<T, void> AtomicSet(T volatile& target, TAtomicBase value) {
  27. AtomicSet(*AsAtomicPtr(&target), value);
  28. }
  29. template <typename T>
  30. inline TEnableIfCastable<T, T> AtomicIncrement(T volatile& target) {
  31. return static_cast<T>(AtomicIncrement(*AsAtomicPtr(&target)));
  32. }
  33. template <typename T>
  34. inline TEnableIfCastable<T, T> AtomicGetAndIncrement(T volatile& target) {
  35. return static_cast<T>(AtomicGetAndIncrement(*AsAtomicPtr(&target)));
  36. }
  37. template <typename T>
  38. inline TEnableIfCastable<T, T> AtomicDecrement(T volatile& target) {
  39. return static_cast<T>(AtomicDecrement(*AsAtomicPtr(&target)));
  40. }
  41. template <typename T>
  42. inline TEnableIfCastable<T, T> AtomicGetAndDecrement(T volatile& target) {
  43. return static_cast<T>(AtomicGetAndDecrement(*AsAtomicPtr(&target)));
  44. }
  45. template <typename T>
  46. inline TEnableIfCastable<T, T> AtomicAdd(T volatile& target, TAtomicBase value) {
  47. return static_cast<T>(AtomicAdd(*AsAtomicPtr(&target), value));
  48. }
  49. template <typename T>
  50. inline TEnableIfCastable<T, T> AtomicGetAndAdd(T volatile& target, TAtomicBase value) {
  51. return static_cast<T>(AtomicGetAndAdd(*AsAtomicPtr(&target), value));
  52. }
  53. template <typename T>
  54. inline TEnableIfCastable<T, T> AtomicSub(T volatile& target, TAtomicBase value) {
  55. return static_cast<T>(AtomicSub(*AsAtomicPtr(&target), value));
  56. }
  57. template <typename T>
  58. inline TEnableIfCastable<T, T> AtomicGetAndSub(T volatile& target, TAtomicBase value) {
  59. return static_cast<T>(AtomicGetAndSub(*AsAtomicPtr(&target), value));
  60. }
  61. template <typename T>
  62. inline TEnableIfCastable<T, T> AtomicSwap(T volatile* target, TAtomicBase exchange) {
  63. return static_cast<T>(AtomicSwap(AsAtomicPtr(target), exchange));
  64. }
  65. template <typename T>
  66. inline TEnableIfCastable<T, bool> AtomicCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) {
  67. return AtomicCas(AsAtomicPtr(target), exchange, compare);
  68. }
  69. template <typename T>
  70. inline TEnableIfCastable<T, T> AtomicGetAndCas(T volatile* target, TAtomicBase exchange, TAtomicBase compare) {
  71. return static_cast<T>(AtomicGetAndCas(AsAtomicPtr(target), exchange, compare));
  72. }
  73. template <typename T>
  74. inline TEnableIfCastable<T, bool> AtomicTryLock(T volatile* target) {
  75. return AtomicTryLock(AsAtomicPtr(target));
  76. }
  77. template <typename T>
  78. inline TEnableIfCastable<T, bool> AtomicTryAndTryLock(T volatile* target) {
  79. return AtomicTryAndTryLock(AsAtomicPtr(target));
  80. }
  81. template <typename T>
  82. inline TEnableIfCastable<T, void> AtomicUnlock(T volatile* target) {
  83. AtomicUnlock(AsAtomicPtr(target));
  84. }
  85. template <typename T>
  86. inline TEnableIfCastable<T, T> AtomicOr(T volatile& target, TAtomicBase value) {
  87. return static_cast<T>(AtomicOr(*AsAtomicPtr(&target), value));
  88. }
  89. template <typename T>
  90. inline TEnableIfCastable<T, T> AtomicAnd(T volatile& target, TAtomicBase value) {
  91. return static_cast<T>(AtomicAnd(*AsAtomicPtr(&target), value));
  92. }
  93. template <typename T>
  94. inline TEnableIfCastable<T, T> AtomicXor(T volatile& target, TAtomicBase value) {
  95. return static_cast<T>(AtomicXor(*AsAtomicPtr(&target), value));
  96. }
  97. // pointer types
  98. template <typename T>
  99. inline T* AtomicGet(T* const volatile& target) {
  100. return reinterpret_cast<T*>(AtomicGet(*AsAtomicPtr(&target)));
  101. }
  102. template <typename T>
  103. inline void AtomicSet(T* volatile& target, T* value) {
  104. AtomicSet(*AsAtomicPtr(&target), reinterpret_cast<TAtomicBase>(value));
  105. }
  106. using TNullPtr = decltype(nullptr);
  107. template <typename T>
  108. inline void AtomicSet(T* volatile& target, TNullPtr) {
  109. AtomicSet(*AsAtomicPtr(&target), 0);
  110. }
  111. template <typename T>
  112. inline T* AtomicSwap(T* volatile* target, T* exchange) {
  113. return reinterpret_cast<T*>(AtomicSwap(AsAtomicPtr(target), reinterpret_cast<TAtomicBase>(exchange)));
  114. }
  115. template <typename T>
  116. inline T* AtomicSwap(T* volatile* target, TNullPtr) {
  117. return reinterpret_cast<T*>(AtomicSwap(AsAtomicPtr(target), 0));
  118. }
  119. template <typename T>
  120. inline bool AtomicCas(T* volatile* target, T* exchange, T* compare) {
  121. return AtomicCas(AsAtomicPtr(target), reinterpret_cast<TAtomicBase>(exchange), reinterpret_cast<TAtomicBase>(compare));
  122. }
  123. template <typename T>
  124. inline T* AtomicGetAndCas(T* volatile* target, T* exchange, T* compare) {
  125. return reinterpret_cast<T*>(AtomicGetAndCas(AsAtomicPtr(target), reinterpret_cast<TAtomicBase>(exchange), reinterpret_cast<TAtomicBase>(compare)));
  126. }
  127. template <typename T>
  128. inline bool AtomicCas(T* volatile* target, T* exchange, TNullPtr) {
  129. return AtomicCas(AsAtomicPtr(target), reinterpret_cast<TAtomicBase>(exchange), 0);
  130. }
  131. template <typename T>
  132. inline T* AtomicGetAndCas(T* volatile* target, T* exchange, TNullPtr) {
  133. return reinterpret_cast<T*>(AtomicGetAndCas(AsAtomicPtr(target), reinterpret_cast<TAtomicBase>(exchange), 0));
  134. }
  135. template <typename T>
  136. inline bool AtomicCas(T* volatile* target, TNullPtr, T* compare) {
  137. return AtomicCas(AsAtomicPtr(target), 0, reinterpret_cast<TAtomicBase>(compare));
  138. }
  139. template <typename T>
  140. inline T* AtomicGetAndCas(T* volatile* target, TNullPtr, T* compare) {
  141. return reinterpret_cast<T*>(AtomicGetAndCas(AsAtomicPtr(target), 0, reinterpret_cast<TAtomicBase>(compare)));
  142. }
  143. template <typename T>
  144. inline bool AtomicCas(T* volatile* target, TNullPtr, TNullPtr) {
  145. return AtomicCas(AsAtomicPtr(target), 0, 0);
  146. }
  147. template <typename T>
  148. inline T* AtomicGetAndCas(T* volatile* target, TNullPtr, TNullPtr) {
  149. return reinterpret_cast<T*>(AtomicGetAndCas(AsAtomicPtr(target), 0, 0));
  150. }