mirror of https://github.com/AxioDL/metaforce.git
Several resource management bug fixes
This commit is contained in:
parent
d440c0ff43
commit
c8d44d181b
|
@ -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<std::mutex> 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<std::mutex> 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<std::string> armatureNames = ds.getArmatureNames();
|
||||
std::vector<std::string> 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<athena::io::FileReader>& 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<std::mutex> lk(const_cast<ProjectResourceFactoryBase*>(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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<IObj>&& obj,
|
||||
const SObjectTag& objTag, CVParamTransfer buildParams)
|
||||
: x4_objTag(objTag), xC_objectStore(&objStore),
|
||||
x10_object(obj.release()), x14_params(buildParams) {}
|
||||
CObjectReference::CObjectReference(std::unique_ptr<IObj>&& 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<IObj>()(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<IObj>()(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<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)
|
||||
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<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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<IObj>&& obj,
|
||||
const SObjectTag& objTag, CVParamTransfer buildParams)
|
||||
: x4_objTag(objTag), xC_objectStore(&objStore),
|
||||
x10_object(obj.release()), x14_params(buildParams) {}
|
||||
CObjectReference(std::unique_ptr<IObj>&& obj)
|
||||
: x10_object(obj.release()) {}
|
||||
const SObjectTag& objTag, CVParamTransfer buildParams);
|
||||
CObjectReference(std::unique_ptr<IObj>&& 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<IObj>()(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<IObj>()(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<CObjectReference>()(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<CToken*>(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<IObj>(obj));
|
||||
++x0_objRef->x0_refCount;
|
||||
Lock();
|
||||
}
|
||||
CToken(std::unique_ptr<IObj>&& 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<IObj>&& obj);
|
||||
const SObjectTag* GetObjectTag() const;
|
||||
~CToken();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit 3a5bdade6f3e26b82eded9bee1bdcec2856fb0df
|
||||
Subproject commit 1326eacf98fdc94d7fd692d248d54de9a09a2fb8
|
Loading…
Reference in New Issue