1 // The MIT License (MIT)
2 //
3 // 	Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev
4 //
5 // 	Permission is hereby granted, free of charge, to any person obtaining a copy
6 // 	of this software and associated documentation files (the "Software"), to deal
7 // 	in the Software without restriction, including without limitation the rights
8 // 	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // 	copies of the Software, and to permit persons to whom the Software is
10 // 	furnished to do so, subject to the following conditions:
11 //
12 //  The above copyright notice and this permission notice shall be included in
13 // 	all copies or substantial portions of the Software.
14 //
15 // 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // 	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // 	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // 	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // 	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // 	THE SOFTWARE.
22 
23 #pragma once
24 
25 #ifndef __MT_ATOMIC__
26 #define __MT_ATOMIC__
27 
28 #include <type_traits>
29 
30 
31 namespace MT
32 {
33 
34 	//
35 	// Full memory barrier
36 	//
37 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
38 	inline void HardwareFullMemoryBarrier()
39 	{
40 		__sync_synchronize();
41 	}
42 
43 	//
44 	// Atomic int (pod type)
45 	//
46 	// You must use this type when you need to declare static variable instead of AtomicInt32
47 	//
48 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49 	struct AtomicInt32Base
50 	{
51 		volatile int32 _value;
52 
53 		int32 AddFetch(int32 sum)
54 		{
55 			return __sync_add_and_fetch(&_value, sum);
56 		}
57 
58 		int32 IncFetch()
59 		{
60 			return __sync_add_and_fetch(&_value, 1);
61 		}
62 
63 		int32 DecFetch()
64 		{
65 			return __sync_sub_and_fetch(&_value, 1);
66 		}
67 
68 		int32 Load() const
69 		{
70 			return _value;
71 		}
72 
73 		int32 Store(int32 val)
74 		{
75 			return __sync_lock_test_and_set(&_value, val);
76 		}
77 
78 		// The function returns the initial value.
79 		int32 CompareAndSwap(int32 compareValue, int32 newValue)
80 		{
81 			return __sync_val_compare_and_swap(&_value, compareValue, newValue);
82 		}
83 
84 		// Relaxed operation: there are no synchronization or ordering constraints
85 		int32 LoadRelaxed() const
86 		{
87 			return _value;
88 		}
89 
90 		// Relaxed operation: there are no synchronization or ordering constraints
91 		void StoreRelaxed(int32 val)
92 		{
93 			_value = val;
94 		}
95 	};
96 
97 
98 	//
99 	// Atomic pointer (pod type)
100 	//
101 	// You must use this type when you need to declare static variable instead of AtomicInt32
102 	//
103 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
104 	struct AtomicPtrBase
105 	{
106 		volatile void* _value;
107 
108 		void* Load() const
109 		{
110 			return (void*)_value;
111 		}
112 
113 		// The function returns the initial value.
114 		void* Store(void* val)
115 		{
116 			void* r = __sync_lock_test_and_set((void**)&_value, val);
117 			return r;
118 		}
119 
120 		// The function returns the initial value.
121 		void* CompareAndSwap(void* compareValue, void* newValue)
122 		{
123 			void* r = __sync_val_compare_and_swap((void**)&_value, compareValue, newValue);
124 			return r;
125 		}
126 
127 		// Relaxed operation: there are no synchronization or ordering constraints
128 		void* LoadRelaxed() const
129 		{
130 			return (void*)_value;
131 		}
132 
133 		// Relaxed operation: there are no synchronization or ordering constraints
134 		void StoreRelaxed(void* val)
135 		{
136 			_value = val;
137 		}
138 
139 	};
140 
141 
142 
143 
144 }
145 
146 #endif