AuroraRuntime/Include/Aurora/Utility/PrivData.hpp

130 lines
4.3 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: PrivData.hpp
Date: 2023-6-3
Author: Reece
Note: This header is included very early on!
***/
#pragma once
// We're very early...
#include <Aurora\Threading\IWaitable.hpp>
#include <Aurora\Threading\Primitives\Primitives.hpp>
#include <Aurora\Threading\LockGuard.hpp>
#if defined(AURORA_USR_DATA_USE_SLOW_PTR)
#define AURT_PRIVATE_DATA_PTR AuSPtr<void>
#else
#define AURT_PRIVATE_DATA_PTR std::shared_ptr<void>
#endif
namespace Aurora::Utility
{
// ! Optional Interface: !
struct IHasPrivateData
{
virtual AURT_PRIVATE_DATA_PTR PrivateUserDataGet() = 0;
virtual AURT_PRIVATE_DATA_PTR PrivateUserDataExchange(AURT_PRIVATE_DATA_PTR, AURT_PRIVATE_DATA_PTR) = 0;
};
namespace Detail
{
struct GetPrivateDataImpl
{
inline virtual AURT_PRIVATE_DATA_PTR GetData()
{
AU_LOCK_GUARD(this->quickMutex);
return this->pData;
}
inline virtual bool ExchangeData(AURT_PRIVATE_DATA_PTR pExpect, AURT_PRIVATE_DATA_PTR pReplace)
{
AU_LOCK_GUARD(this->quickMutex);
auto pData = this->pData;
if (pData != pExpect)
{
return false;
}
this->pData = pExpect;
return true;
}
Aurora::Threading::Primitives::Mutex quickMutex;
AURT_PRIVATE_DATA_PTR pData {};
};
}
}
#define AURT_ADD_USR_DATA \
private: \
Aurora::Utility::Detail::GetPrivateDataImpl _auReservedUserData; \
public:\
inline virtual AURT_PRIVATE_DATA_PTR PrivateUserDataGet()\
{\
return this->_auReservedUserData.GetData();\
}\
inline virtual bool PrivateUserDataExchange(AURT_PRIVATE_DATA_PTR pExpect, AURT_PRIVATE_DATA_PTR pReplace)\
{\
return this->_auReservedUserData.ExchangeData(pExpect, pReplace);\
}\
template<typename T>\
inline AuSPtr<T> PrivateUserDataNewData()\
{\
auto pCurrent = this->_auReservedUserData.pData;\
if (pCurrent) return {};\
auto pMaybeTemp = AuMakeShared<T>();\
if (!pMaybeTemp) return {};\
return (this->PrivateUserDataExchange(pCurrent, pMaybeTemp)) ? pMaybeTemp : AURT_PRIVATE_DATA_PTR {};\
}\
template<typename T>\
inline AuSPtr<T> PrivateUserDataGetSharedData()\
{\
auto pCurrent = this->_auReservedUserData.pData;\
if (pCurrent) return AuReinterpretCast<T>(pCurrent);\
auto pMaybeTemp = AuMakeShared<T>();\
if (!pMaybeTemp) return {};\
return (this->PrivateUserDataExchange(pCurrent, pMaybeTemp)) ? pMaybeTemp : AuReinterpretCast<T>(this->_auReservedUserData.pData);\
}\
inline Aurora::Threading::Primitives::IHyperWaitable *PrivateUserDataToUtilityMutex()\
{\
return this->_auReservedUserData.quickMutex.AsPointer();\
}\
protected:\
inline void PrivateUserDataClear()\
{\
AuResetMember(this->_auReservedUserData.pData);\
}
#define AURT_ADD_USR_DATA_EXP(exp) \
inline virtual AURT_PRIVATE_DATA_PTR PrivateUserDataGet()\
{\
return exp->PrivateUserDataGet();\
}\
inline virtual bool PrivateUserDataExchange(AURT_PRIVATE_DATA_PTR pExpect, AURT_PRIVATE_DATA_PTR pReplace)\
{\
return exp->PrivateUserDataExchange(pExpect, pReplace);\
}\
template<typename T>\
inline AuSPtr<T> PrivateUserDataNewData()\
{\
return exp->PrivateUserDataNewData<T>();\
}\
template<typename T>\
inline AuSPtr<T> PrivateUserDataGetSharedData()\
{\
return exp->PrivateUserDataGetSharedData<T>();\
}\
inline Aurora::Threading::Primitives::IHyperWaitable *PrivateUserDataToUtilityMutex()\
{\
return exp->PrivateUserDataToUtilityMutex();\
}
#if defined(AURORA_USR_DATA_DISABLED)
#undef AURT_ADD_USR_DATA
#define AURT_ADD_USR_DATA
#define AURT_ADD_USR_DATA_ON_SHIP
#else
#define AURT_ADD_USR_DATA_ON_SHIP AURT_ADD_USR_DATA
#endif