#include "Runtime/CToken.hpp" namespace metaforce { u16 CObjectReference::RemoveReference() { --x0_refCount; if (x0_refCount == 0) { if (x10_object) Unload(); if (IsLoading()) CancelLoad(); if (xC_objectStore) xC_objectStore->ObjectUnreferenced(x4_objTag); } return x0_refCount; } CObjectReference::CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, const SObjectTag& objTag, CVParamTransfer buildParams) : x4_objTag(objTag), xC_objectStore(&objStore), x10_object(std::move(obj)), x14_params(std::move(buildParams)) {} CObjectReference::CObjectReference(std::unique_ptr&& obj) : x10_object(std::move(obj)) {} void CObjectReference::Unlock() { --x2_lockCount; if (x2_lockCount) return; if (x10_object && xC_objectStore) Unload(); else if (IsLoading()) CancelLoad(); } void CObjectReference::Lock() { ++x2_lockCount; if (!x10_object && !x3_loading) { IFactory& fac = xC_objectStore->GetFactory(); fac.BuildAsync(x4_objTag, x14_params, &x10_object, this); x3_loading = !x10_object.operator bool(); } } void CObjectReference::CancelLoad() { if ((xC_objectStore != nullptr) && IsLoading()) { xC_objectStore->GetFactory().CancelBuild(x4_objTag); x3_loading = false; } } void CObjectReference::Unload() { x10_object.reset(); x3_loading = false; } IObj* CObjectReference::GetObject() { if (!x10_object) { IFactory& factory = xC_objectStore->GetFactory(); x10_object = factory.Build(x4_objTag, x14_params, this); } x3_loading = false; return x10_object.get(); } CObjectReference::~CObjectReference() { if (x10_object) x10_object.reset(); else if (x3_loading) xC_objectStore->GetFactory().CancelBuild(x4_objTag); } void CToken::RemoveRef() { if (x0_objRef && x0_objRef->RemoveReference() == 0) { std::default_delete()(x0_objRef); x0_objRef = nullptr; } } CToken::CToken(CObjectReference* obj) { x0_objRef = obj; ++x0_objRef->x0_refCount; } void CToken::Unlock() { if (x0_objRef && x4_lockHeld) { x0_objRef->Unlock(); x4_lockHeld = false; } } void CToken::Lock() { if (x0_objRef && !x4_lockHeld) { x0_objRef->Lock(); x4_lockHeld = true; } } bool CToken::IsLoaded() const { if (!x0_objRef || !x4_lockHeld) return false; return x0_objRef->IsLoaded(); } IObj* CToken::GetObj() { if (!x0_objRef) return nullptr; Lock(); return x0_objRef->GetObject(); } CToken& CToken::operator=(const CToken& other) { if (this == &other) return *this; Unlock(); RemoveRef(); x0_objRef = other.x0_objRef; if (x0_objRef) { ++x0_objRef->x0_refCount; if (other.x4_lockHeld) Lock(); } return *this; } CToken& CToken::operator=(CToken&& other) noexcept { Unlock(); RemoveRef(); x0_objRef = other.x0_objRef; other.x0_objRef = nullptr; x4_lockHeld = other.x4_lockHeld; other.x4_lockHeld = false; return *this; } CToken::CToken(const CToken& other) : x0_objRef(other.x0_objRef) { if (x0_objRef) { ++x0_objRef->x0_refCount; if (other.x4_lockHeld) Lock(); } } CToken::CToken(CToken&& other) noexcept : x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld) { other.x0_objRef = nullptr; other.x4_lockHeld = false; } CToken::CToken(IObj* obj) { x0_objRef = new CObjectReference(std::unique_ptr(obj)); ++x0_objRef->x0_refCount; Lock(); } CToken::CToken(std::unique_ptr&& obj) { x0_objRef = new CObjectReference(std::move(obj)); ++x0_objRef->x0_refCount; Lock(); } const SObjectTag* CToken::GetObjectTag() const { if (!x0_objRef) return nullptr; return &x0_objRef->GetObjectTag(); } CToken::~CToken() { if (x0_objRef) { if (x4_lockHeld) x0_objRef->Unlock(); RemoveRef(); } } } // namespace metaforce