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 }