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 #include <MTTypes.h>
26 #include <MTDebug.h>
27 
28 typedef void (*TThreadEntryPoint)(void* userData);
29 
30 #define MT_ARRAY_SIZE( arr ) ( sizeof( arr ) / sizeof( (arr)[0] ) )
31 
32 namespace MT
33 {
34 	namespace EventReset
35 	{
36 		enum Type
37 		{
38 			AUTOMATIC = 0,
39 			MANUAL = 1,
40 		};
41 	}
42 }
43 
44 
45 inline bool IsPointerAligned( const volatile void* p, const uint32 align )
46 {
47 	return !((uintptr_t)p & (align - 1));
48 }
49 
50 #ifdef _WIN32
51 	#include <Platform/Windows/MTCommon.h>
52 #else
53 	#include <Platform/Posix/MTCommon.h>
54 #endif
55 
56 
57 namespace MT
58 {
59 	//compile time POD type check
60 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61 	static_assert(std::is_pod<AtomicInt32Base>::value == true, "AtomicInt32Base must be a POD (plain old data type)");
62 
63 
64 	//
65 	// Atomic int (type with constructor)
66 	//
67 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
68 	class AtomicInt32 : public AtomicInt32Base
69 	{
70 
71 	public:
72 
73 		AtomicInt32()
74 		{
75 			_value = 0;
76 			static_assert(sizeof(AtomicInt32) == 4, "Invalid type size");
77 			static_assert(sizeof(int32) == sizeof(long), "Incompatible types, Interlocked* will fail");
78 			MT_ASSERT(IsPointerAligned(&_value, 4), "Invalid atomic int alignment");
79 		}
80 
81 		explicit AtomicInt32(int v)
82 		{
83 			_value = v;
84 			static_assert(sizeof(AtomicInt32) == 4, "Invalid type size");
85 			static_assert(sizeof(int32) == sizeof(long), "Incompatible types, Interlocked* will fail");
86 			MT_ASSERT(IsPointerAligned(&_value, 4), "Invalid atomic int alignment");
87 		}
88 	};
89 
90 
91 	//compile time POD type check
92 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
93 	static_assert(std::is_pod<AtomicPtrBase>::value == true, "AtomicPtrBase must be a POD (plain old data type)");
94 
95 
96 	//
97 	// Atomic pointer (type with constructor)
98 	//
99 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100 	template<typename T>
101 	class AtomicPtr : protected AtomicPtrBase
102 	{
103 	public:
104 		AtomicPtr()
105 		{
106 			_value = nullptr;
107 			MT_ASSERT(IsPointerAligned(&_value, sizeof(void*)), "Invalid atomic ptr alignment");
108 		}
109 
110 		explicit AtomicPtr(T* v)
111 		{
112 			_value = v;
113 			MT_ASSERT(IsPointerAligned(&_value, sizeof(void*)), "Invalid atomic ptr alignment");
114 		}
115 
116 		T* Load() const
117 		{
118 			return (T*)AtomicPtrBase::Load();
119 		}
120 
121 		T* Store(T* val)
122 		{
123 			return (T*)AtomicPtrBase::Store(val);
124 		}
125 
126 
127 		T* CompareAndSwap(T* compareValue, T* newValue)
128 		{
129 			return (T*)AtomicPtrBase::CompareAndSwap(compareValue, newValue);
130 		}
131 
132 		T* LoadRelaxed() const
133 		{
134 			return (T*)AtomicPtrBase::LoadRelaxed();
135 		}
136 
137 		void StoreRelaxed(T* val)
138 		{
139 			AtomicPtrBase::StoreRelaxed(val);
140 		}
141 	};
142 
143 
144 
145 
146 	//
147 	//
148 	//
149 	class ScopedGuard
150 	{
151 		MT::Mutex & mutex;
152 
153 		ScopedGuard( const ScopedGuard & ) : mutex(*((MT::Mutex*)nullptr)) {}
154 		void operator=( const ScopedGuard &) {}
155 
156 	public:
157 
158 		ScopedGuard(MT::Mutex & _mutex) : mutex(_mutex)
159 		{
160 			mutex.Lock();
161 		}
162 
163 		~ScopedGuard()
164 		{
165 			mutex.Unlock();
166 		}
167 	};
168 
169 	//
170 	// Simple Linear congruential generator
171 	//
172 	class LcgRandom
173 	{
174 		uint32 state;
175 
176 	public:
177 
178 		LcgRandom()
179 			: state(2578432553)
180 		{
181 		}
182 
183 		void SetSeed(uint32 seed)
184 		{
185 			state = seed;
186 		}
187 
188 		uint16 Get()
189 		{
190 			state = 214013 * state + 2531011;
191 			uint16 rnd = (state >> 16);
192 			return rnd;
193 		}
194 
195 
196 	};
197 
198 }
199 
200