2018-10-07 03:42:33 +00:00
|
|
|
#pragma once
|
2015-08-21 00:06:39 +00:00
|
|
|
|
2015-08-22 01:58:41 +00:00
|
|
|
#include <memory>
|
2019-09-23 19:00:23 +00:00
|
|
|
|
|
|
|
#include "Runtime/IFactory.hpp"
|
|
|
|
#include "Runtime/IObj.hpp"
|
|
|
|
#include "Runtime/IObjectStore.hpp"
|
|
|
|
#include "Runtime/IVParamObj.hpp"
|
|
|
|
#include "Runtime/RetroTypes.hpp"
|
2015-08-22 01:58:41 +00:00
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
namespace metaforce {
|
2015-08-22 01:58:41 +00:00
|
|
|
class IObjectStore;
|
|
|
|
|
2016-02-09 05:05:36 +00:00
|
|
|
/** Shared data-structure for CToken references, analogous to std::shared_ptr */
|
2018-12-08 05:30:43 +00:00
|
|
|
class CObjectReference {
|
|
|
|
friend class CSimplePool;
|
2019-09-23 19:00:23 +00:00
|
|
|
friend class CToken;
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
u16 x0_refCount = 0;
|
|
|
|
u16 x2_lockCount = 0;
|
|
|
|
bool x3_loading = false; /* Rightmost bit of lockCount */
|
|
|
|
SObjectTag x4_objTag;
|
|
|
|
IObjectStore* xC_objectStore = nullptr;
|
|
|
|
std::unique_ptr<IObj> x10_object;
|
|
|
|
CVParamTransfer x14_params;
|
2016-04-01 01:00:37 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset.
|
|
|
|
* Reaching 0 indicates the CToken should delete the CObjectReference */
|
|
|
|
u16 RemoveReference();
|
2016-04-01 01:00:37 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CObjectReference(IObjectStore& objStore, std::unique_ptr<IObj>&& obj, const SObjectTag& objTag,
|
|
|
|
CVParamTransfer buildParams);
|
|
|
|
CObjectReference(std::unique_ptr<IObj>&& obj);
|
2015-08-22 01:58:41 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Indicates an asynchronous load transaction has been submitted and is not yet finished */
|
|
|
|
bool IsLoading() const { return x3_loading; }
|
2016-02-09 05:05:36 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Indicates an asynchronous load transaction has finished and object is completely loaded */
|
|
|
|
bool IsLoaded() const { return x10_object.operator bool(); }
|
2016-03-20 00:32:30 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */
|
|
|
|
void Unlock();
|
2016-02-09 05:05:36 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Increments 2nd ref-count, performing async-factory-load if needed */
|
|
|
|
void Lock();
|
2016-02-09 05:05:36 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void CancelLoad();
|
2016-02-09 05:05:36 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */
|
|
|
|
void Unload();
|
2016-02-09 05:05:36 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
/** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */
|
|
|
|
IObj* GetObject();
|
2016-09-21 05:41:51 +00:00
|
|
|
|
2016-04-01 01:00:37 +00:00
|
|
|
public:
|
2018-12-08 05:30:43 +00:00
|
|
|
const SObjectTag& GetObjectTag() const { return x4_objTag; }
|
2018-05-20 06:14:57 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
~CObjectReference();
|
2015-08-22 01:58:41 +00:00
|
|
|
};
|
2015-08-21 00:06:39 +00:00
|
|
|
|
2016-02-09 05:05:36 +00:00
|
|
|
/** Counted meta-object, reference-counting against a shared CObjectReference
|
|
|
|
* This class is analogous to std::shared_ptr and C++11 rvalues have been implemented accordingly
|
|
|
|
* (default/empty constructor, move constructor/assign) */
|
2018-12-08 05:30:43 +00:00
|
|
|
class CToken {
|
|
|
|
friend class CModel;
|
2019-09-23 19:00:23 +00:00
|
|
|
friend class CSimplePool;
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CObjectReference* x0_objRef = nullptr;
|
|
|
|
bool x4_lockHeld = false;
|
2016-04-01 01:00:37 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
void RemoveRef();
|
2016-04-01 01:00:37 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
CToken(CObjectReference* obj);
|
2016-04-01 01:00:37 +00:00
|
|
|
|
2015-08-22 01:58:41 +00:00
|
|
|
public:
|
2018-12-08 05:30:43 +00:00
|
|
|
/* Added to test for non-null state */
|
2020-03-09 01:10:15 +00:00
|
|
|
explicit operator bool() const { return HasReference(); }
|
|
|
|
bool HasReference() const { return x0_objRef != nullptr; }
|
|
|
|
|
2020-03-13 08:11:17 +00:00
|
|
|
void Unlock();
|
2018-12-08 05:30:43 +00:00
|
|
|
void Lock();
|
|
|
|
bool IsLocked() const { return x4_lockHeld; }
|
|
|
|
bool IsLoaded() const;
|
|
|
|
IObj* GetObj();
|
|
|
|
const IObj* GetObj() const { return const_cast<CToken*>(this)->GetObj(); }
|
2020-03-13 08:11:17 +00:00
|
|
|
CToken& operator=(const CToken& other);
|
2020-03-28 00:56:01 +00:00
|
|
|
CToken& operator=(CToken&& other) noexcept;
|
2018-12-08 05:30:43 +00:00
|
|
|
CToken() = default;
|
|
|
|
CToken(const CToken& other);
|
2019-09-30 06:24:11 +00:00
|
|
|
CToken(CToken&& other) noexcept;
|
2018-12-08 05:30:43 +00:00
|
|
|
CToken(IObj* obj);
|
|
|
|
CToken(std::unique_ptr<IObj>&& obj);
|
|
|
|
const SObjectTag* GetObjectTag() const;
|
|
|
|
~CToken();
|
2015-08-21 00:06:39 +00:00
|
|
|
};
|
|
|
|
|
2016-02-08 05:10:17 +00:00
|
|
|
template <class T>
|
2018-12-08 05:30:43 +00:00
|
|
|
class TToken : public CToken {
|
2016-02-05 01:27:03 +00:00
|
|
|
public:
|
2018-12-08 05:30:43 +00:00
|
|
|
static std::unique_ptr<TObjOwnerDerivedFromIObj<T>> GetIObjObjectFor(std::unique_ptr<T>&& obj) {
|
|
|
|
return TObjOwnerDerivedFromIObj<T>::GetNewDerivedObject(std::move(obj));
|
|
|
|
}
|
|
|
|
TToken() = default;
|
2020-03-13 08:11:17 +00:00
|
|
|
virtual ~TToken() = default;
|
2018-12-08 05:30:43 +00:00
|
|
|
TToken(const CToken& other) : CToken(other) {}
|
|
|
|
TToken(CToken&& other) : CToken(std::move(other)) {}
|
|
|
|
TToken(std::unique_ptr<T>&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {}
|
|
|
|
TToken& operator=(std::unique_ptr<T>&& obj) {
|
|
|
|
*this = CToken(GetIObjObjectFor(std::move(obj)));
|
2020-04-17 21:16:31 +00:00
|
|
|
return *this;
|
2018-12-08 05:30:43 +00:00
|
|
|
}
|
2020-03-13 08:11:17 +00:00
|
|
|
virtual void Unlock() { CToken::Unlock(); }
|
|
|
|
virtual void Lock() { CToken::Lock(); }
|
2020-03-12 23:30:33 +00:00
|
|
|
virtual T* GetObj() {
|
2018-12-08 05:30:43 +00:00
|
|
|
TObjOwnerDerivedFromIObj<T>* owner = static_cast<TObjOwnerDerivedFromIObj<T>*>(CToken::GetObj());
|
|
|
|
if (owner)
|
|
|
|
return owner->GetObj();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2020-03-12 23:30:33 +00:00
|
|
|
virtual const T* GetObj() const { return const_cast<TToken<T>*>(this)->GetObj(); }
|
2020-03-13 08:11:17 +00:00
|
|
|
virtual TToken& operator=(const CToken& other) {
|
|
|
|
CToken::operator=(other);
|
|
|
|
return *this;
|
|
|
|
}
|
2018-12-08 05:30:43 +00:00
|
|
|
T* operator->() { return GetObj(); }
|
|
|
|
const T* operator->() const { return GetObj(); }
|
|
|
|
T& operator*() { return *GetObj(); }
|
|
|
|
const T& operator*() const { return *GetObj(); }
|
2016-02-05 01:27:03 +00:00
|
|
|
};
|
|
|
|
|
2016-02-08 05:10:17 +00:00
|
|
|
template <class T>
|
2018-12-08 05:30:43 +00:00
|
|
|
class TCachedToken : public TToken<T> {
|
2016-03-31 02:44:43 +00:00
|
|
|
protected:
|
2018-12-08 05:30:43 +00:00
|
|
|
T* m_obj = nullptr;
|
|
|
|
|
2016-03-31 02:44:43 +00:00
|
|
|
public:
|
2018-12-08 05:30:43 +00:00
|
|
|
TCachedToken() = default;
|
|
|
|
TCachedToken(const CToken& other) : TToken<T>(other) {}
|
|
|
|
TCachedToken(CToken&& other) : TToken<T>(std::move(other)) {}
|
2020-03-29 07:20:44 +00:00
|
|
|
T* GetObj() override {
|
2018-12-08 05:30:43 +00:00
|
|
|
if (!m_obj)
|
|
|
|
m_obj = TToken<T>::GetObj();
|
|
|
|
return m_obj;
|
|
|
|
}
|
2020-03-29 07:20:44 +00:00
|
|
|
const T* GetObj() const override { return const_cast<TCachedToken<T>*>(this)->GetObj(); }
|
|
|
|
void Unlock() override {
|
2018-12-08 05:30:43 +00:00
|
|
|
TToken<T>::Unlock();
|
|
|
|
m_obj = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
TCachedToken& operator=(const TCachedToken& other) {
|
2020-03-13 08:11:17 +00:00
|
|
|
TToken<T>::operator=(other);
|
2018-12-08 05:30:43 +00:00
|
|
|
m_obj = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
2020-03-28 09:55:17 +00:00
|
|
|
TCachedToken& operator=(const CToken& other) override {
|
2020-03-13 08:11:17 +00:00
|
|
|
TToken<T>::operator=(other);
|
2018-12-08 05:30:43 +00:00
|
|
|
m_obj = nullptr;
|
|
|
|
return *this;
|
|
|
|
}
|
2022-02-04 08:10:09 +00:00
|
|
|
|
2022-02-25 07:45:25 +00:00
|
|
|
bool IsNull() const { return m_obj == nullptr; }
|
2016-03-31 02:44:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
2018-12-08 05:30:43 +00:00
|
|
|
class TLockedToken : public TCachedToken<T> {
|
2016-02-05 01:27:03 +00:00
|
|
|
public:
|
2018-12-08 05:30:43 +00:00
|
|
|
TLockedToken() = default;
|
|
|
|
TLockedToken(const TLockedToken& other) : TCachedToken<T>(other) { CToken::Lock(); }
|
|
|
|
TLockedToken& operator=(const TLockedToken& other) {
|
|
|
|
CToken oldTok = std::move(*this);
|
|
|
|
TCachedToken<T>::operator=(other);
|
|
|
|
CToken::Lock();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
TLockedToken(const CToken& other) : TCachedToken<T>(other) { CToken::Lock(); }
|
2020-03-28 09:55:17 +00:00
|
|
|
TLockedToken& operator=(const CToken& other) override {
|
2018-12-08 05:30:43 +00:00
|
|
|
CToken oldTok = std::move(*this);
|
|
|
|
TCachedToken<T>::operator=(other);
|
|
|
|
CToken::Lock();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
TLockedToken(CToken&& other) {
|
|
|
|
CToken oldTok = std::move(*this);
|
|
|
|
*this = TCachedToken<T>(std::move(other));
|
|
|
|
CToken::Lock();
|
|
|
|
}
|
2015-08-21 00:06:39 +00:00
|
|
|
};
|
|
|
|
|
2021-04-10 08:42:06 +00:00
|
|
|
} // namespace metaforce
|