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 		// The function returns the resulting added value.
48 		int Add(int sum)
49 		{
50 			return InterlockedExchangeAdd(&value, sum) + sum;
51 		}
52 
53 		// The function returns the resulting incremented value.
54 		int Inc()
55 		{
56 			return InterlockedIncrement(&value);
57 		}
58 
59 		// The function returns the resulting decremented value.
60 		int Dec()
61 		{
62 			return InterlockedDecrement(&value);
63 		}
64 
65 		int Get() const
66 		{
67 			return value;
68 		}
69 
70 		// The function returns the initial value.
71 		int Set(int val)
72 		{
73 			return InterlockedExchange(&value, val);
74 		}
75 
76 		// The function returns the initial value.
77 		int CompareAndSwap(int compareValue, int newValue)
78 		{
79 			return InterlockedCompareExchange(&value, newValue, compareValue);
80 		}
81 	};
82 
83 
84 	//
85 	// Atomic pointer
86 	//
87 	template<typename T>
88 	class AtomicPtr
89 	{
90 		volatile T* value;
91 
92 	public:
93 
94 		AtomicPtr()
95 			: value(nullptr)
96 		{
97 			MT_ASSERT(IsPointerAligned(&value, sizeof(void*)), "Invalid atomic ptr alignment");
98 		}
99 
100 		explicit AtomicPtr(T* v)
101 			: value(v)
102 		{
103 			MT_ASSERT(IsPointerAligned(&value, sizeof(void*)), "Invalid atomic ptr alignment");
104 		}
105 
106 		T* Get() const
107 		{
108 			return (T*)value;
109 		}
110 
111 		// The function returns the initial value.
112 		T* Set(T* val)
113 		{
114 			return (T*)InterlockedExchangePointer((PVOID volatile *)&value, (void*)val);
115 		}
116 
117 		// The function returns the initial value.
118 		T* CompareAndSwap(T* compareValue, T* newValue)
119 		{
120 			return (T*)InterlockedCompareExchangePointer((PVOID volatile *)&value, (void*)newValue, (void*)compareValue);
121 		}
122 	};
123 
124 
125 }
126