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 
2566de1283SSergey Makeev 
2666de1283SSergey Makeev #ifdef _WIN32
2766de1283SSergey Makeev #include <Platform/Windows/MTAtomic.h>
2866de1283SSergey Makeev #else
2966de1283SSergey Makeev #include <Platform/Posix/MTAtomic.h>
3066de1283SSergey Makeev #endif
3166de1283SSergey Makeev 
3266de1283SSergey Makeev 
3366de1283SSergey Makeev 
3466de1283SSergey Makeev namespace MT
3566de1283SSergey Makeev {
36*27dbb6f7Ss.makeev 	inline bool IsPointerAligned( const volatile void* p, const uint32 align )
37*27dbb6f7Ss.makeev 	{
38*27dbb6f7Ss.makeev 		return !((uintptr_t)p & (align - 1));
39*27dbb6f7Ss.makeev 	}
40*27dbb6f7Ss.makeev 
41*27dbb6f7Ss.makeev 
4266de1283SSergey Makeev 	//compile time POD type check
4366de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4466de1283SSergey Makeev 	static_assert(std::is_pod<AtomicInt32Base>::value == true, "AtomicInt32Base must be a POD (plain old data type)");
4566de1283SSergey Makeev 
4666de1283SSergey Makeev 
4766de1283SSergey Makeev 	//
4866de1283SSergey Makeev 	// Atomic int (type with constructor)
4966de1283SSergey Makeev 	//
5066de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5166de1283SSergey Makeev 	class AtomicInt32 : public AtomicInt32Base
5266de1283SSergey Makeev 	{
5366de1283SSergey Makeev 
5466de1283SSergey Makeev 	public:
5566de1283SSergey Makeev 
5666de1283SSergey Makeev 		AtomicInt32()
5766de1283SSergey Makeev 		{
5866de1283SSergey Makeev 			_value = 0;
5966de1283SSergey Makeev 			static_assert(sizeof(AtomicInt32) == 4, "Invalid type size");
6066de1283SSergey Makeev 			MT_ASSERT(IsPointerAligned(&_value, 4), "Invalid atomic int alignment");
6166de1283SSergey Makeev 		}
6266de1283SSergey Makeev 
6366de1283SSergey Makeev 		explicit AtomicInt32(int v)
6466de1283SSergey Makeev 		{
6566de1283SSergey Makeev 			_value = v;
6666de1283SSergey Makeev 			static_assert(sizeof(AtomicInt32) == 4, "Invalid type size");
6766de1283SSergey Makeev 			MT_ASSERT(IsPointerAligned(&_value, 4), "Invalid atomic int alignment");
6866de1283SSergey Makeev 		}
6966de1283SSergey Makeev 	};
7066de1283SSergey Makeev 
7166de1283SSergey Makeev 
7266de1283SSergey Makeev 	//compile time POD type check
7366de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7466de1283SSergey Makeev 	static_assert(std::is_pod<AtomicPtrBase>::value == true, "AtomicPtrBase must be a POD (plain old data type)");
7566de1283SSergey Makeev 
7666de1283SSergey Makeev 
7766de1283SSergey Makeev 	//
7866de1283SSergey Makeev 	// Atomic pointer (type with constructor)
7966de1283SSergey Makeev 	//
8066de1283SSergey Makeev 	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8166de1283SSergey Makeev 	template<typename T>
8266de1283SSergey Makeev 	class AtomicPtr : protected AtomicPtrBase
8366de1283SSergey Makeev 	{
8466de1283SSergey Makeev 	public:
8566de1283SSergey Makeev 		AtomicPtr()
8666de1283SSergey Makeev 		{
8766de1283SSergey Makeev 			_value = nullptr;
8866de1283SSergey Makeev 			MT_ASSERT(IsPointerAligned(&_value, sizeof(void*)), "Invalid atomic ptr alignment");
8966de1283SSergey Makeev 		}
9066de1283SSergey Makeev 
9166de1283SSergey Makeev 		explicit AtomicPtr(T* v)
9266de1283SSergey Makeev 		{
9366de1283SSergey Makeev 			_value = v;
9466de1283SSergey Makeev 			MT_ASSERT(IsPointerAligned(&_value, sizeof(void*)), "Invalid atomic ptr alignment");
9566de1283SSergey Makeev 		}
9666de1283SSergey Makeev 
9766de1283SSergey Makeev 		T* Load() const
9866de1283SSergey Makeev 		{
9966de1283SSergey Makeev 			return (T*)AtomicPtrBase::Load();
10066de1283SSergey Makeev 		}
10166de1283SSergey Makeev 
10266de1283SSergey Makeev 		T* Store(T* val)
10366de1283SSergey Makeev 		{
10466de1283SSergey Makeev 			return (T*)AtomicPtrBase::Store(val);
10566de1283SSergey Makeev 		}
10666de1283SSergey Makeev 
10766de1283SSergey Makeev 
10866de1283SSergey Makeev 		T* CompareAndSwap(T* compareValue, T* newValue)
10966de1283SSergey Makeev 		{
11066de1283SSergey Makeev 			return (T*)AtomicPtrBase::CompareAndSwap(compareValue, newValue);
11166de1283SSergey Makeev 		}
11266de1283SSergey Makeev 
11366de1283SSergey Makeev 		T* LoadRelaxed() const
11466de1283SSergey Makeev 		{
11566de1283SSergey Makeev 			return (T*)AtomicPtrBase::LoadRelaxed();
11666de1283SSergey Makeev 		}
11766de1283SSergey Makeev 
11866de1283SSergey Makeev 		void StoreRelaxed(T* val)
11966de1283SSergey Makeev 		{
12066de1283SSergey Makeev 			AtomicPtrBase::StoreRelaxed(val);
12166de1283SSergey Makeev 		}
12266de1283SSergey Makeev 	};
12366de1283SSergey Makeev }