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 namespace MT
26 {
27 	//
28 	// Atomic int
29 	//
30 	class AtomicInt
31 	{
32 		volatile long value;
33 	public:
34 
35 		AtomicInt()
36 			: value(0)
37 		{
38 			MT_ASSERT(IsPointerAligned(&value, 4), "Invalid atomic int alignment");
39 		}
40 
41 		explicit AtomicInt(int v)
42 			: value(v)
43 		{
44 			MT_ASSERT(IsPointerAligned(&value, 4), "Invalid atomic int alignment");
45 		}
46 
47 		int Add(int sum)
48 		{
49 			return __sync_add_and_fetch(&value, sum);
50 		}
51 
52 		int Inc()
53 		{
54 			return __sync_add_and_fetch(&value, 1);
55 		}
56 
57 		int Dec()
58 		{
59 			return __sync_sub_and_fetch(&value, 1);
60 		}
61 
62 		int Get() const
63 		{
64 			return value;
65 		}
66 
67 		int Set(int val)
68 		{
69 			return __sync_lock_test_and_set(&value, val);
70 		}
71 
72 		// The function returns the initial value.
73 		int CompareAndSwap(int compareValue, int newValue)
74 		{
75 			return __sync_val_compare_and_swap(&value, compareValue, newValue);
76 		}
77 
78 	};
79 
80 
81 	//
82 	// Atomic pointer
83 	//
84 	template<typename T>
85 	class AtomicPtr
86 	{
87 		volatile T* value;
88 
89 	public:
90 
91 		AtomicPtr()
92 			: value(nullptr)
93 		{
94 			MT_ASSERT(IsPointerAligned(&value, sizeof(void*)), "Invalid atomic ptr alignment");
95 		}
96 
97 		explicit AtomicPtr(T* v)
98 			: value(v)
99 		{
100 			MT_ASSERT(IsPointerAligned(&value, sizeof(void*)), "Invalid atomic ptr alignment");
101 		}
102 
103 		T* Get() const
104 		{
105 			return (T*)value;
106 		}
107 
108 		// The function returns the initial value.
109 		T* Set(T* val)
110 		{
111 			void* r = __sync_lock_test_and_set((void**)&value, (void*)val);
112 			return (T*)r;
113 		}
114 
115 		// The function returns the initial value.
116 		T* CompareAndSwap(T* compareValue, T* newValue)
117 		{
118 			void* r = __sync_val_compare_and_swap((void**)&value, (void*)compareValue, (void*)newValue);
119 			return (T*)r;
120 		}
121 	};
122 
123 
124 }
125