metaforce/Runtime/CToken.hpp

190 lines
5.6 KiB
C++
Raw Normal View History

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