#pragma once #include #include #include "SharedPtr.h" class AtomicSharedPtrBase { public: void Reset() { Reset(nullptr, nullptr, false); } protected: void* volatile _object; RefCount* volatile _refCount; AtomicSharedPtrBase() : _object(nullptr), _refCount(nullptr) { } AtomicSharedPtrBase(void* object, RefCount* refCount) : _object(object), _refCount(refCount) { } ~AtomicSharedPtrBase() { Reset(nullptr, nullptr, false); } void Reset(void* newObject, RefCount* newRefCount, bool increaseNewRefCount); }; template class AtomicSharedPtr : public AtomicSharedPtrBase { public: AtomicSharedPtr() { } AtomicSharedPtr(std::nullptr_t) { } AtomicSharedPtr(const SharedPtr& sharedPtr) : AtomicSharedPtrBase(sharedPtr._object, sharedPtr._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } template requires std::assignable_from AtomicSharedPtr(const SharedPtr& sharedPtr) : AtomicSharedPtrBase(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } template explicit AtomicSharedPtr(const SharedPtr& sharedPtr) : AtomicSharedPtrBase(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount) { if (_refCount) { shared_ptr_increase_ref_count(_refCount->refCount); } } AtomicSharedPtr(SharedPtr&& sharedPtr) : AtomicSharedPtrBase(sharedPtr._object, sharedPtr._refCount) { sharedPtr._object = nullptr; sharedPtr._refCount = nullptr; } template requires std::assignable_from AtomicSharedPtr(SharedPtr&& sharedPtr) : AtomicSharedPtrBase(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount) { sharedPtr._object = nullptr; sharedPtr._refCount = nullptr; } template explicit AtomicSharedPtr(SharedPtr&& sharedPtr) : AtomicSharedPtrBase(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount) { sharedPtr._object = nullptr; sharedPtr._refCount = nullptr; } AtomicSharedPtr& operator=(const SharedPtr& sharedPtr) { Reset(sharedPtr._object, sharedPtr._refCount, true); return *this; } template requires std::assignable_from AtomicSharedPtr& operator=(const SharedPtr& sharedPtr) { Reset(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount, true); return *this; } AtomicSharedPtr& operator=(SharedPtr&& sharedPtr) { Reset(sharedPtr._object, sharedPtr._refCount, false); sharedPtr._object = nullptr; sharedPtr._refCount = nullptr; return *this; } template requires std::assignable_from AtomicSharedPtr& operator=(SharedPtr&& sharedPtr) { Reset(static_cast(sharedPtr.GetPointer()), sharedPtr._refCount, false); sharedPtr._object = nullptr; sharedPtr._refCount = nullptr; return *this; } SharedPtr Lock() const { u32 irq = rtos_disableIrqs(); auto object = static_cast(_object); auto refCount = _refCount; if (refCount) { refCount->refCount++; } rtos_restoreIrqs(irq); return SharedPtr(object, refCount); } };