From c8d44d181bb4859e1ad1239f99087e39790e3057 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 20 Sep 2016 19:41:51 -1000 Subject: [PATCH] Several resource management bug fixes --- Editor/ProjectResourceFactoryBase.cpp | 63 +++++--- Editor/ProjectResourceFactoryMP1.cpp | 120 ++++++++++------ Editor/ViewManager.cpp | 2 +- Runtime/CMakeLists.txt | 2 +- Runtime/CToken.cpp | 191 +++++++++++++++++++++++++ Runtime/CToken.hpp | 198 ++++---------------------- hecl | 2 +- 7 files changed, 338 insertions(+), 240 deletions(-) create mode 100644 Runtime/CToken.cpp diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 54326f192..ba9b7ed3c 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -60,12 +60,18 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat const athena::io::YAMLNode* root = reader.getRootNode(); for (const auto& p : root->m_mapChildren) { + /* Hash as lowercase since lookup is case-insensitive */ + std::string pLower = p.first; + std::transform(pLower.cbegin(), pLower.cend(), pLower.begin(), tolower); + /* Avoid redundant filesystem access for re-caches */ - if (m_catalogNameToTag.find(p.first) != m_catalogNameToTag.cend()) + if (m_catalogNameToTag.find(pLower) != m_catalogNameToTag.cend()) continue; athena::io::YAMLNode& node = *p.second; hecl::ProjectPath path(m_proj->getProjectWorkingPath(), node.m_scalarString); + if (node.m_scalarString == "MP1/SamGunFx/PowerBeam.wpsm.yaml") + printf(""); if (node.m_type == YAML_SCALAR_NODE) { path = hecl::ProjectPath(m_proj->getProjectWorkingPath(), node.m_scalarString); @@ -84,7 +90,7 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); - m_catalogNameToTag[p.first] = pathTag; + m_catalogNameToTag[pLower] = pathTag; WriteNameTag(nameWriter, pathTag, p.first); #if 0 fprintf(stderr, "%s %s %08X\n", @@ -144,25 +150,29 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, if (m_pathToTag.find(path.hash()) != m_pathToTag.cend()) return true; + /* Try as glob */ + hecl::ProjectPath asGlob = path.getWithExtension(_S(".*"), true); + if (m_pathToTag.find(asGlob.hash()) != m_pathToTag.cend()) + return true; + /* Classify intermediate into tag */ SObjectTag pathTag = BuildTagFromPath(path, m_backgroundBlender); if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); - m_tagToPath[pathTag] = path; - m_pathToTag[path.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, path); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, path); -#endif + bool useGlob = false; /* Special multi-resource intermediates */ if (pathTag.type == SBIG('ANCS')) - { + { hecl::BlenderConnection& conn = m_backgroundBlender.getBlenderConnection(); if (!conn.openBlend(path) || conn.getBlendType() != hecl::BlenderConnection::BlendType::Actor) return false; + /* Transform tag to glob */ + pathTag = {SBIG('ANCS'), asGlob.hash().val32()}; + useGlob = true; + hecl::BlenderConnection::DataStream ds = conn.beginData(); std::vector armatureNames = ds.getArmatureNames(); std::vector subtypeNames = ds.getSubtypeNames(); @@ -171,7 +181,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, for (const std::string& arm : armatureNames) { hecl::SystemStringView sysStr(arm); - hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".CINF")); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".CINF")); SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; @@ -184,7 +194,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, for (const std::string& sub : subtypeNames) { hecl::SystemStringView sysStr(sub); - hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR")); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR")); SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; @@ -197,7 +207,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, for (const std::string& act : actionNames) { hecl::SystemStringView sysStr(act); - hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM")); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM")); SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender); m_tagToPath[pathTag] = subPath; m_pathToTag[subPath.hash()] = pathTag; @@ -207,6 +217,15 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path, #endif } } + + /* Cache in-memory */ + const hecl::ProjectPath& usePath = useGlob ? asGlob : path; + m_tagToPath[pathTag] = usePath; + m_pathToTag[usePath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, usePath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, usePath); +#endif } return true; @@ -239,6 +258,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec continue; } + /* Index the regular file */ AddFileToIndex(path, cacheWriter); } @@ -286,7 +306,7 @@ void ProjectResourceFactoryBase::BackgroundIndexProc() path = path.ensureAuxInfo(sys.sys_str()); } - if (path.isFile()) + if (path.isFileOrGlob()) { SObjectTag pathTag(type, id); m_tagToPath[pathTag] = path; @@ -317,8 +337,10 @@ void ProjectResourceFactoryBase::BackgroundIndexProc() auto search = m_tagToPath.find(SObjectTag(FourCC(), uint32_t(id))); if (search != m_tagToPath.cend()) { - m_catalogNameToTag[child.first] = search->first; - WriteNameTag(nameWriter, search->first, child.first); + std::string chLower = child.first; + std::transform(chLower.cbegin(), chLower.cend(), chLower.begin(), tolower); + m_catalogNameToTag[chLower] = search->first; + WriteNameTag(nameWriter, search->first, chLower); } } } @@ -412,7 +434,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t m_workingPath = path; /* Ensure requested resource is on the filesystem */ - if (!path.isFile()) + if (!path.isFileOrGlob()) { Log.report(logvisor::Error, _S("unable to find resource path '%s'"), path.getRelativePath().c_str()); @@ -523,7 +545,7 @@ ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, std::experimental::optional& fr) { /* Ensure requested resource is on the filesystem */ - if (!path.isFile()) + if (!path.isFileOrGlob()) { Log.report(logvisor::Error, _S("unable to find resource path '%s'"), path.getAbsolutePath().c_str()); @@ -724,8 +746,11 @@ bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const char* name) const { + std::string lower = name; + std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower); + std::unique_lock lk(const_cast(this)->m_backgroundIndexMutex); - auto search = m_catalogNameToTag.find(name); + auto search = m_catalogNameToTag.find(lower); if (search == m_catalogNameToTag.end()) { if (m_backgroundRunning) @@ -734,7 +759,7 @@ const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const ch { lk.unlock(); lk.lock(); - search = m_catalogNameToTag.find(name); + search = m_catalogNameToTag.find(lower); if (search != m_catalogNameToTag.end()) break; } diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index ea01c1035..6a7cb7813 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -64,10 +64,16 @@ SObjectTag ProjectResourceFactoryMP1::BuildTagFromPath(const hecl::ProjectPath& else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".ANIM"))) return SObjectTag(SBIG('ANIM'), path.hash().val32()); - if (hecl::IsPathBlend(path)) + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_S(".blend"), true); + else + asBlend = path; + + if (hecl::IsPathBlend(asBlend)) { hecl::BlenderConnection& conn = btok.getBlenderConnection(); - if (!conn.openBlend(path)) + if (!conn.openBlend(asBlend)) return {}; switch (conn.getBlendType()) @@ -113,49 +119,75 @@ SObjectTag ProjectResourceFactoryMP1::BuildTagFromPath(const hecl::ProjectPath& yaml_parser_set_input_file(reader.getParser(), fp); SObjectTag resTag; - if (reader.ClassTypeOperation([&](const char* className) -> bool { - if (!strcmp(className, "GPSM")) - { - resTag.type = SBIG('PART'); - return true; - } - else if (!strcmp(className, "FONT")) - { - resTag.type = SBIG('FONT'); - return true; - } - else if (!strcmp(className, "urde::DNAMP1::EVNT")) - { - resTag.type = SBIG('EVNT'); - return true; - } - else if (!strcmp(className, "urde::DGRP")) - { - resTag.type = SBIG('DGRP'); - return true; - } - else if (!strcmp(className, "urde::DNAMP1::STRG")) - { - resTag.type = SBIG('STRG'); - return true; - } - else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") || - !strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") || - !strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") || - !strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") || - !strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob")) - { - resTag.type = SBIG('CTWK'); - return true; - } - else if (!strcmp(className, "DataSpec::DNAMP1::HINT")) - { - resTag.type = SBIG('HINT'); - return true; - } + if (reader.ClassTypeOperation([&](const char* className) -> bool + { + if (!strcmp(className, "GPSM")) + { + resTag.type = SBIG('PART'); + return true; + } + if (!strcmp(className, "SWSH")) + { + resTag.type = SBIG('SWHC'); + return true; + } + if (!strcmp(className, "ELSM")) + { + resTag.type = SBIG('ELSC'); + return true; + } + if (!strcmp(className, "WPSM")) + { + resTag.type = SBIG('WPSC'); + return true; + } + if (!strcmp(className, "CRSM")) + { + resTag.type = SBIG('CRSC'); + return true; + } + if (!strcmp(className, "DPSM")) + { + resTag.type = SBIG('DPSC'); + return true; + } + else if (!strcmp(className, "FONT")) + { + resTag.type = SBIG('FONT'); + return true; + } + else if (!strcmp(className, "urde::DNAMP1::EVNT")) + { + resTag.type = SBIG('EVNT'); + return true; + } + else if (!strcmp(className, "urde::DGRP")) + { + resTag.type = SBIG('DGRP'); + return true; + } + else if (!strcmp(className, "urde::DNAMP1::STRG")) + { + resTag.type = SBIG('STRG'); + return true; + } + else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") || + !strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") || + !strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") || + !strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") || + !strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob")) + { + resTag.type = SBIG('CTWK'); + return true; + } + else if (!strcmp(className, "DataSpec::DNAMP1::HINT")) + { + resTag.type = SBIG('HINT'); + return true; + } - return false; - })) + return false; + })) { resTag.id = path.hash().val32(); fclose(fp); diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index 3dca4c904..61951e2b3 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -29,7 +29,7 @@ void ViewManager::BuildTestPART(urde::IObjectStore& objStore) m_modelTest = objStore.GetObj("MP1/Shared/CMDL_B2B41738.blend"); CModel* ridley = m_modelTest.GetObj(); #if 1 - SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.blend")); + SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.*")); SObjectTag platModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_6FA561D0.blend")); SObjectTag bgModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_BC34D54C.blend")); CAnimRes samusAnimRes(samusCharSet.id, 2, zeus::CVector3f{2.f, 2.f, 2.f}, 1, true); diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index bb81edb98..2a093780f 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -85,7 +85,7 @@ add_library(RuntimeCommon IObj.hpp IVParamObj.hpp CTimeProvider.hpp CTimeProvider.cpp - CToken.hpp + CToken.hpp CToken.cpp CFactoryMgr.hpp CFactoryMgr.cpp CPakFile.hpp CPakFile.cpp CStringExtras.hpp diff --git a/Runtime/CToken.cpp b/Runtime/CToken.cpp new file mode 100644 index 000000000..732e24f6b --- /dev/null +++ b/Runtime/CToken.cpp @@ -0,0 +1,191 @@ +#include "CToken.hpp" + +namespace urde +{ +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(obj.release()), x14_params(buildParams) {} +CObjectReference::CObjectReference(std::unique_ptr&& obj) +: x10_object(obj.release()) {} + +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 = true; + } +} + +void CObjectReference::CancelLoad() +{ + if (xC_objectStore && IsLoading()) + { + xC_objectStore->GetFactory().CancelBuild(x4_objTag); + x3_loading = false; + } +} + +void CObjectReference::Unload() +{ + std::default_delete()(x10_object); + x10_object = nullptr; + x3_loading = false; +} + +IObj* CObjectReference::GetObject() +{ + if (!x10_object) + { + IFactory& factory = xC_objectStore->GetFactory(); + x10_object = factory.Build(x4_objTag, x14_params, this).release(); + } + x3_loading = false; + return x10_object; +} + +CObjectReference::~CObjectReference() +{ + if (x10_object) + std::default_delete()(x10_object); + 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) + 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) +{ + 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) +{ + 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; +} +CToken::CToken(CToken&& other) +: 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(); + } +} + +} diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index abbbf9dc0..70f98bc31 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -27,27 +27,11 @@ class CObjectReference /** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset. * Reaching 0 indicates the CToken should delete the CObjectReference */ - u16 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; - } + u16 RemoveReference(); CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, - const SObjectTag& objTag, CVParamTransfer buildParams) - : x4_objTag(objTag), xC_objectStore(&objStore), - x10_object(obj.release()), x14_params(buildParams) {} - CObjectReference(std::unique_ptr&& obj) - : x10_object(obj.release()) {} + const SObjectTag& objTag, CVParamTransfer buildParams); + CObjectReference(std::unique_ptr&& obj); /** Indicates an asynchronous load transaction has been submitted and is not yet finished */ bool IsLoading() const {return x3_loading;} @@ -56,70 +40,26 @@ class CObjectReference bool IsLoaded() const {return x10_object != nullptr;} /** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */ - void Unlock() - { - --x2_lockCount; - if (x2_lockCount) - return; - if (x10_object && xC_objectStore) - Unload(); - else if (IsLoading()) - CancelLoad(); - } + void Unlock(); /** Increments 2nd ref-count, performing async-factory-load if needed */ - void Lock() - { - ++x2_lockCount; - if (!x10_object && !x3_loading) - { - IFactory& fac = xC_objectStore->GetFactory(); - fac.BuildAsync(x4_objTag, x14_params, &x10_object, this); - x3_loading = true; - } - } + void Lock(); - void CancelLoad() - { - if (xC_objectStore && IsLoading()) - { - xC_objectStore->GetFactory().CancelBuild(x4_objTag); - x3_loading = false; - } - } + void CancelLoad(); /** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */ - void Unload() - { - std::default_delete()(x10_object); - x10_object = nullptr; - x3_loading = false; - } + void Unload(); /** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */ - IObj* GetObject() - { - if (!x10_object) - { - IFactory& factory = xC_objectStore->GetFactory(); - x10_object = factory.Build(x4_objTag, x14_params, this).release(); - } - x3_loading = false; - return x10_object; - } + IObj* GetObject(); + const SObjectTag& GetObjectTag() const { return x4_objTag; } public: - ~CObjectReference() - { - if (x10_object) - std::default_delete()(x10_object); - else if (x3_loading) - xC_objectStore->GetFactory().CancelBuild(x4_objTag); - } + ~CObjectReference(); }; /** Counted meta-object, reference-counting against a shared CObjectReference @@ -132,121 +72,31 @@ class CToken CObjectReference* x0_objRef = nullptr; bool x4_lockHeld = false; - void RemoveRef() - { - if (x0_objRef && x0_objRef->RemoveReference() == 0) - { - std::default_delete()(x0_objRef); - x0_objRef = nullptr; - } - } + void RemoveRef(); - CToken(CObjectReference* obj) - { - x0_objRef = obj; - ++x0_objRef->x0_refCount; - } + CToken(CObjectReference* obj); public: /* Added to test for non-null state */ operator bool() const {return x0_objRef != nullptr;} - void Unlock() - { - if (x0_objRef && x4_lockHeld) - { - x0_objRef->Unlock(); - x4_lockHeld = false; - } - } - void Lock() - { - if (x0_objRef && !x4_lockHeld) - { - x0_objRef->Lock(); - x4_lockHeld = true; - } - } + void Unlock(); + void Lock(); bool IsLocked() const {return x4_lockHeld;} - bool IsLoaded() const - { - if (!x0_objRef) - return false; - return x0_objRef->IsLoaded(); - } - IObj* GetObj() - { - if (!x0_objRef) - return nullptr; - Lock(); - return x0_objRef->GetObject(); - } + bool IsLoaded() const; + IObj* GetObj(); const IObj* GetObj() const { return const_cast(this)->GetObj(); } - CToken& operator=(const CToken& other) - { - Unlock(); - RemoveRef(); - x0_objRef = other.x0_objRef; - if (x0_objRef) - { - ++x0_objRef->x0_refCount; - if (other.x4_lockHeld) - Lock(); - } - return *this; - } - CToken& operator=(CToken&& other) - { - Unlock(); - RemoveRef(); - x0_objRef = other.x0_objRef; - other.x0_objRef = nullptr; - x4_lockHeld = other.x4_lockHeld; - other.x4_lockHeld = false; - return *this; - } + CToken& operator=(const CToken& other); + CToken& operator=(CToken&& other); CToken() = default; - CToken(const CToken& other) - : x0_objRef(other.x0_objRef) - { - if (x0_objRef) - ++x0_objRef->x0_refCount; - } - CToken(CToken&& other) - : x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld) - { - other.x0_objRef = nullptr; - other.x4_lockHeld = false; - } - CToken(IObj* obj) - { - x0_objRef = new CObjectReference(std::unique_ptr(obj)); - ++x0_objRef->x0_refCount; - Lock(); - } - CToken(std::unique_ptr&& obj) - { - x0_objRef = new CObjectReference(std::move(obj)); - ++x0_objRef->x0_refCount; - Lock(); - } - const SObjectTag* GetObjectTag() const - { - if (!x0_objRef) - return nullptr; - return &x0_objRef->GetObjectTag(); - } - ~CToken() - { - if (x0_objRef) - { - if (x4_lockHeld) - x0_objRef->Unlock(); - RemoveRef(); - } - } + CToken(const CToken& other); + CToken(CToken&& other); + CToken(IObj* obj); + CToken(std::unique_ptr&& obj); + const SObjectTag* GetObjectTag() const; + ~CToken(); }; template diff --git a/hecl b/hecl index 3a5bdade6..1326eacf9 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 3a5bdade6f3e26b82eded9bee1bdcec2856fb0df +Subproject commit 1326eacf98fdc94d7fd692d248d54de9a09a2fb8