#pragma once namespace WAVM { // A smart pointer that uses an intrusive reference counter. // Needs Pointee to define memory functions to manipulate the reference count: // void addRef(); // void removeRef(); template struct IntrusiveSharedPtr { // Constructors/destructor constexpr IntrusiveSharedPtr() : value(nullptr) {} IntrusiveSharedPtr(Pointee* inValue) { value = inValue; if(value) { value->addRef(); } } IntrusiveSharedPtr(const IntrusiveSharedPtr& inCopy) { value = inCopy.value; if(value) { value->addRef(); } } IntrusiveSharedPtr(IntrusiveSharedPtr&& inMove) { value = inMove.value; inMove.value = nullptr; } ~IntrusiveSharedPtr() { if(value) { value->removeRef(); } } // Adopt a raw pointer: coerces the pointer to an IntrusiveSharedPtr without calling addRef // or removeRef. static IntrusiveSharedPtr adopt(Pointee*&& inValue) { IntrusiveSharedPtr result(adoptConstructorSelector, inValue); inValue = nullptr; return result; } // Assignment operators void operator=(Pointee* inValue) { auto oldValue = value; value = inValue; if(value) { value->addRef(); } if(oldValue) { oldValue->removeRef(); } } void operator=(const IntrusiveSharedPtr& inCopy) { auto oldValue = value; value = inCopy.value; if(value) { value->addRef(); } if(oldValue) { oldValue->removeRef(); } } void operator=(IntrusiveSharedPtr&& inMove) { auto oldValue = value; value = inMove.value; inMove.value = nullptr; if(oldValue) { oldValue->removeRef(); } } // Accessors constexpr operator Pointee*() const { return value; } constexpr Pointee& operator*() const { return *value; } constexpr Pointee* operator->() const { return value; } private: Pointee* value; enum AdoptConstructorSelector { adoptConstructorSelector }; constexpr IntrusiveSharedPtr(AdoptConstructorSelector, Pointee* inValue) : value(inValue) {} }; }