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