166de1283SSergey Makeev // The MIT License (MIT)
266de1283SSergey Makeev //
366de1283SSergey Makeev // 	Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev
466de1283SSergey Makeev //
566de1283SSergey Makeev // 	Permission is hereby granted, free of charge, to any person obtaining a copy
666de1283SSergey Makeev // 	of this software and associated documentation files (the "Software"), to deal
766de1283SSergey Makeev // 	in the Software without restriction, including without limitation the rights
866de1283SSergey Makeev // 	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
966de1283SSergey Makeev // 	copies of the Software, and to permit persons to whom the Software is
1066de1283SSergey Makeev // 	furnished to do so, subject to the following conditions:
1166de1283SSergey Makeev //
1266de1283SSergey Makeev //  The above copyright notice and this permission notice shall be included in
1366de1283SSergey Makeev // 	all copies or substantial portions of the Software.
1466de1283SSergey Makeev //
1566de1283SSergey Makeev // 	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1666de1283SSergey Makeev // 	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1766de1283SSergey Makeev // 	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1866de1283SSergey Makeev // 	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1966de1283SSergey Makeev // 	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2066de1283SSergey Makeev // 	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2166de1283SSergey Makeev // 	THE SOFTWARE.
2266de1283SSergey Makeev 
2366de1283SSergey Makeev #pragma once
2466de1283SSergey Makeev 
2502d170cfSs.makeev_local #include <MTConfig.h>
2666de1283SSergey Makeev 
2702d170cfSs.makeev_local #if MT_MSVC_COMPILER_FAMILY
2866de1283SSergey Makeev #include <Platform/Windows/MTAtomic.h>
2902d170cfSs.makeev_local #elif MT_PLATFORM_POSIX || MT_PLATFORM_OSX
3066de1283SSergey Makeev #include <Platform/Posix/MTAtomic.h>
3102d170cfSs.makeev_local #else
3266de1283SSergey Makeev #endif
3366de1283SSergey Makeev 
3466de1283SSergey Makeev 
3566de1283SSergey Makeev 
3666de1283SSergey Makeev namespace MT
3766de1283SSergey Makeev {
IsPointerAligned(const volatile void * p,const uint32 align)3827dbb6f7Ss.makeev 	inline bool IsPointerAligned( const volatile void* p, const uint32 align )
3927dbb6f7Ss.makeev 	{
4027dbb6f7Ss.makeev 		return !((uintptr_t)p & (align - 1));
4127dbb6f7Ss.makeev 	}
4227dbb6f7Ss.makeev 
4327dbb6f7Ss.makeev 
4466de1283SSergey Makeev 	//
4566de1283SSergey Makeev 	// Atomic int (type with constructor)
4666de1283SSergey Makeev 	//
4766de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48*721f8c0bSs.makeev_local 	template<typename T>
49*721f8c0bSs.makeev_local 	class Atomic32 : public Atomic32Base<T>
5066de1283SSergey Makeev 	{
5166de1283SSergey Makeev 
5266de1283SSergey Makeev 	public:
5366de1283SSergey Makeev 
Atomic32()54*721f8c0bSs.makeev_local 		Atomic32()
5566de1283SSergey Makeev 		{
56*721f8c0bSs.makeev_local 			static_assert(sizeof(Atomic32<T>) == sizeof(T), "Invalid atomic type size");
57*721f8c0bSs.makeev_local 			MT_ASSERT(IsPointerAligned(this, __alignof(T)), "Invalid atomic alignment");
58*721f8c0bSs.makeev_local 
59*721f8c0bSs.makeev_local 			Atomic32Base<T>::Store(0);
6066de1283SSergey Makeev 		}
6166de1283SSergey Makeev 
Atomic32(T v)62*721f8c0bSs.makeev_local 		explicit Atomic32(T v)
6366de1283SSergey Makeev 		{
64*721f8c0bSs.makeev_local 			static_assert(sizeof(Atomic32<T>) == sizeof(T), "Invalid atomic type size");
65*721f8c0bSs.makeev_local 			MT_ASSERT(IsPointerAligned(this, __alignof(T)), "Invalid atomic alignment");
66*721f8c0bSs.makeev_local 
67*721f8c0bSs.makeev_local 			Atomic32Base<T>::Store(v);
6866de1283SSergey Makeev 		}
6966de1283SSergey Makeev 	};
7066de1283SSergey Makeev 
7166de1283SSergey Makeev 
7266de1283SSergey Makeev 	//
7366de1283SSergey Makeev 	// Atomic pointer (type with constructor)
7466de1283SSergey Makeev 	//
7566de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7666de1283SSergey Makeev 	template<typename T>
77*721f8c0bSs.makeev_local 	class AtomicPtr : public AtomicPtrBase<T>
7866de1283SSergey Makeev 	{
7966de1283SSergey Makeev 	public:
AtomicPtr()8066de1283SSergey Makeev 		AtomicPtr()
8166de1283SSergey Makeev 		{
82*721f8c0bSs.makeev_local 			static_assert(sizeof(AtomicPtr<T>) == sizeof(T*), "Invalid atomic type size");
83*721f8c0bSs.makeev_local 			MT_ASSERT(IsPointerAligned(this, sizeof(T*)), "Invalid atomic ptr alignment");
84*721f8c0bSs.makeev_local 
85*721f8c0bSs.makeev_local 			AtomicPtrBase<T>::Store(nullptr);
8666de1283SSergey Makeev 		}
8766de1283SSergey Makeev 
AtomicPtr(T * v)8866de1283SSergey Makeev 		explicit AtomicPtr(T* v)
8966de1283SSergey Makeev 		{
90*721f8c0bSs.makeev_local 			static_assert(sizeof(AtomicPtr<T>) == sizeof(T*), "Invalid atomic type size");
91*721f8c0bSs.makeev_local 			MT_ASSERT(IsPointerAligned(this, sizeof(T*)), "Invalid atomic ptr alignment");
92*721f8c0bSs.makeev_local 
93*721f8c0bSs.makeev_local 			AtomicPtrBase<T>::Store(v);
9466de1283SSergey Makeev 		}
9566de1283SSergey Makeev 
9666de1283SSergey Makeev 	};
9766de1283SSergey Makeev }