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
21namespace
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