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