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 <MTConfig.h>
26 
27 #if MT_MSVC_COMPILER_FAMILY
28 #include <Platform/Windows/MTAtomic.h>
29 #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX
30 #include <Platform/Posix/MTAtomic.h>
31 #else
32 #endif
33 
34 
35 
36 namespace MT
37 {
IsPointerAligned(const volatile void * p,const uint32 align)38 	inline bool IsPointerAligned( const volatile void* p, const uint32 align )
39 	{
40 		return !((uintptr_t)p & (align - 1));
41 	}
42 
43 
44 	//
45 	// Atomic int (type with constructor)
46 	//
47 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48 	template<typename T>
49 	class Atomic32 : public Atomic32Base<T>
50 	{
51 
52 	public:
53 
Atomic32()54 		Atomic32()
55 		{
56 			static_assert(sizeof(Atomic32<T>) == sizeof(T), "Invalid atomic type size");
57 			MT_ASSERT(IsPointerAligned(this, __alignof(T)), "Invalid atomic alignment");
58 
59 			Atomic32Base<T>::Store(0);
60 		}
61 
Atomic32(T v)62 		explicit Atomic32(T v)
63 		{
64 			static_assert(sizeof(Atomic32<T>) == sizeof(T), "Invalid atomic type size");
65 			MT_ASSERT(IsPointerAligned(this, __alignof(T)), "Invalid atomic alignment");
66 
67 			Atomic32Base<T>::Store(v);
68 		}
69 	};
70 
71 
72 	//
73 	// Atomic pointer (type with constructor)
74 	//
75 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
76 	template<typename T>
77 	class AtomicPtr : public AtomicPtrBase<T>
78 	{
79 	public:
AtomicPtr()80 		AtomicPtr()
81 		{
82 			static_assert(sizeof(AtomicPtr<T>) == sizeof(T*), "Invalid atomic type size");
83 			MT_ASSERT(IsPointerAligned(this, sizeof(T*)), "Invalid atomic ptr alignment");
84 
85 			AtomicPtrBase<T>::Store(nullptr);
86 		}
87 
AtomicPtr(T * v)88 		explicit AtomicPtr(T* v)
89 		{
90 			static_assert(sizeof(AtomicPtr<T>) == sizeof(T*), "Invalid atomic type size");
91 			MT_ASSERT(IsPointerAligned(this, sizeof(T*)), "Invalid atomic ptr alignment");
92 
93 			AtomicPtrBase<T>::Store(v);
94 		}
95 
96 	};
97 }