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 #include <xmmintrin.h>
30 
31 
32 namespace MT
33 {
34 
35 	//
36 	// Full memory barrier
37 	//
38 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
39 	inline void HardwareFullMemoryBarrier()
40 	{
41 		__sync_synchronize();
42 	}
43 
44 	//
45 	// Signals to the processor to give resources to threads that are waiting for them.
46 	//
47 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48 	inline void YieldCpu()
49 	{
50 		_mm_pause();
51 	}
52 
53 	//
54 	// Atomic int (pod type)
55 	//
56 	// You must use this type when you need to declare static variable instead of AtomicInt32
57 	//
58 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
59 	struct AtomicInt32Base
60 	{
61 		volatile int32 _value;
62 
63 		int32 AddFetch(int32 sum)
64 		{
65 			return __sync_add_and_fetch(&_value, sum);
66 		}
67 
68 		int32 IncFetch()
69 		{
70 			return __sync_add_and_fetch(&_value, 1);
71 		}
72 
73 		int32 DecFetch()
74 		{
75 			return __sync_sub_and_fetch(&_value, 1);
76 		}
77 
78 		int32 Load() const
79 		{
80 			return _value;
81 		}
82 
83 		int32 Store(int32 val)
84 		{
85 			return __sync_lock_test_and_set(&_value, val);
86 		}
87 
88 		// The function returns the initial value.
89 		int32 CompareAndSwap(int32 compareValue, int32 newValue)
90 		{
91 			return __sync_val_compare_and_swap(&_value, compareValue, newValue);
92 		}
93 
94 		// Relaxed operation: there are no synchronization or ordering constraints
95 		int32 LoadRelaxed() const
96 		{
97 			return _value;
98 		}
99 
100 		// Relaxed operation: there are no synchronization or ordering constraints
101 		void StoreRelaxed(int32 val)
102 		{
103 			_value = val;
104 		}
105 	};
106 
107 
108 	//
109 	// Atomic pointer (pod type)
110 	//
111 	// You must use this type when you need to declare static variable instead of AtomicInt32
112 	//
113 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114 	struct AtomicPtrBase
115 	{
116 		volatile const void* _value;
117 
118 		const void* Load() const
119 		{
120 			return (void*)_value;
121 		}
122 
123 		// The function returns the initial value.
124 		const void* Store(const void* val)
125 		{
126 			const void* r = __sync_lock_test_and_set((void**)&_value, (void*)val);
127 			return r;
128 		}
129 
130 		// The function returns the initial value.
131 		const void* CompareAndSwap(const void* compareValue, const void* newValue)
132 		{
133 			const void* r = __sync_val_compare_and_swap((void**)&_value, (void*)compareValue, (void*)newValue);
134 			return r;
135 		}
136 
137 		// Relaxed operation: there are no synchronization or ordering constraints
138 		const void* LoadRelaxed() const
139 		{
140 			return (const void*)_value;
141 		}
142 
143 		// Relaxed operation: there are no synchronization or ordering constraints
144 		void StoreRelaxed(const void* val)
145 		{
146 			_value = val;
147 		}
148 
149 	};
150 
151 
152 
153 
154 }
155 
156 #endif