metaforce/Runtime/CToken.cpp

161 lines
3.8 KiB
C++

#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<IObj>&& 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<IObj>&& 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<CObjectReference>()(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<IObj>(obj));
++x0_objRef->x0_refCount;
Lock();
}
CToken::CToken(std::unique_ptr<IObj>&& 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