aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/cxxsupp/libcxxrt/atomic.h
blob: 0768c08038df2e84b650e1d75b24197189bfd009 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#ifndef __has_builtin
#	define __has_builtin(x) 0
#endif
#ifndef __has_feature
#	define __has_feature(x) 0
#endif
#ifndef __has_extension
#	define __has_extension(x) 0
#endif

#if !__has_extension(c_atomic)
#	define _Atomic(T) T
#endif
#if __has_builtin(__c11_atomic_exchange)
#	define ATOMIC_BUILTIN(name) __c11_atomic_##name
#else
#	define ATOMIC_BUILTIN(name) __atomic_##name##_n
#endif

namespace
{
	/**
	 * C++11 memory orders.  We only need a subset of them.
	 */
	enum memory_order
	{
		/**
		 * Acquire order.
		 */
		acquire = __ATOMIC_ACQUIRE,

		/**
		 * Release order.
		 */
		release = __ATOMIC_RELEASE,

		/**
		 * Sequentially consistent memory ordering.
		 */
		seqcst = __ATOMIC_SEQ_CST
	};

	/**
	 * Atomic, implements a subset of `std::atomic`.
	 */
	template<typename T>
	class atomic
	{
		/**
		 * The underlying value.  Use C11 atomic qualification if available.
		 */
		_Atomic(T) val;

		public:
		/**
		 * Constructor, takes a value.
		 */
		constexpr atomic(T init) : val(init) {}

		/**
		 * Atomically load with the specified memory order.
		 */
		T load(memory_order order = memory_order::seqcst)
		{
			return ATOMIC_BUILTIN(load)(&val, order);
		}

		/**
		 * Atomically store with the specified memory order.
		 */
		void store(T v, memory_order order = memory_order::seqcst)
		{
			return ATOMIC_BUILTIN(store)(&val, v, order);
		}

		/**
		 * Atomically exchange with the specified memory order.
		 */
		T exchange(T v, memory_order order = memory_order::seqcst)
		{
			return ATOMIC_BUILTIN(exchange)(&val, v, order);
		}

		/**
		 * Atomically exchange with the specified memory order.
		 */
		bool compare_exchange(T &          expected,
		                      T            desired,
		                      memory_order order = memory_order::seqcst)
		{
#if __has_builtin(__c11_atomic_compare_exchange_strong)
			return __c11_atomic_compare_exchange_strong(
			  &val, &expected, desired, order, order);
#else
			return __atomic_compare_exchange_n(
			  &val, &expected, desired, true, order, order);
#endif
		}
	};
} // namespace
#undef ATOMIC_BUILTIN