atomic.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #ifndef __has_builtin
  2. # define __has_builtin(x) 0
  3. #endif
  4. #ifndef __has_feature
  5. # define __has_feature(x) 0
  6. #endif
  7. #ifndef __has_extension
  8. # define __has_extension(x) 0
  9. #endif
  10. #if !__has_extension(c_atomic)
  11. # define _Atomic(T) T
  12. #endif
  13. #if __has_builtin(__c11_atomic_exchange)
  14. # define ATOMIC_BUILTIN(name) __c11_atomic_##name
  15. #else
  16. # define ATOMIC_BUILTIN(name) __atomic_##name##_n
  17. #endif
  18. namespace
  19. {
  20. /**
  21. * C++11 memory orders. We only need a subset of them.
  22. */
  23. enum memory_order
  24. {
  25. /**
  26. * Acquire order.
  27. */
  28. acquire = __ATOMIC_ACQUIRE,
  29. /**
  30. * Release order.
  31. */
  32. release = __ATOMIC_RELEASE,
  33. /**
  34. * Sequentially consistent memory ordering.
  35. */
  36. seqcst = __ATOMIC_SEQ_CST
  37. };
  38. /**
  39. * Atomic, implements a subset of `std::atomic`.
  40. */
  41. template<typename T>
  42. class atomic
  43. {
  44. /**
  45. * The underlying value. Use C11 atomic qualification if available.
  46. */
  47. _Atomic(T) val;
  48. public:
  49. /**
  50. * Constructor, takes a value.
  51. */
  52. constexpr atomic(T init) : val(init) {}
  53. /**
  54. * Atomically load with the specified memory order.
  55. */
  56. T load(memory_order order = memory_order::seqcst)
  57. {
  58. return ATOMIC_BUILTIN(load)(&val, order);
  59. }
  60. /**
  61. * Atomically store with the specified memory order.
  62. */
  63. void store(T v, memory_order order = memory_order::seqcst)
  64. {
  65. return ATOMIC_BUILTIN(store)(&val, v, order);
  66. }
  67. /**
  68. * Atomically exchange with the specified memory order.
  69. */
  70. T exchange(T v, memory_order order = memory_order::seqcst)
  71. {
  72. return ATOMIC_BUILTIN(exchange)(&val, v, order);
  73. }
  74. /**
  75. * Atomically exchange with the specified memory order.
  76. */
  77. bool compare_exchange(T & expected,
  78. T desired,
  79. memory_order order = memory_order::seqcst)
  80. {
  81. #if __has_builtin(__c11_atomic_compare_exchange_strong)
  82. return __c11_atomic_compare_exchange_strong(
  83. &val, &expected, desired, order, order);
  84. #else
  85. return __atomic_compare_exchange_n(
  86. &val, &expected, desired, true, order, order);
  87. #endif
  88. }
  89. };
  90. } // namespace
  91. #undef ATOMIC_BUILTIN