[+] Early impl of allocless destruction callbacks for adal (AuUtility::DestructionWatch and AuUtility::ADestructionWatcher)

This commit is contained in:
Reece Wilson 2024-01-22 02:03:51 +00:00
parent 34e49d2d10
commit 63858cfcb9
3 changed files with 153 additions and 0 deletions

View File

@ -97,6 +97,7 @@
#include "CmdLine/CmdLine.hpp"
#include "Utility/RateLimiter.hpp"
#include "Memory/_ByteBuffer.hpp"
#include "Utility/DestructionWatch.hpp"
#include "RuntimeAliases.hpp"

View File

@ -51,6 +51,8 @@ namespace AuMemory = Aurora::Memory;
namespace AuHashing = Aurora::Hashing;
namespace AuExit = Aurora::Exit;
namespace AuUtility = Aurora::Utility;
using AuWorkerId_t = AuAsync::WorkerId_t;
using AuWorkerPId_t = AuAsync::WorkerPId_t;
using AuWorkerId = AuAsync::WorkerId_t;

View File

@ -0,0 +1,150 @@
/***
Copyright (C) 2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: DestructionWatch.hpp
Date: 2024-01-22
Author: Reece
***/
#pragma once
namespace Aurora::Utility
{
struct ADestructionWatcher;
struct DestructionWatch
{
inline DestructionWatch();
inline ~DestructionWatch();
inline void RemoveAll();
private:
friend struct ADestructionWatcher;
Threading::Waitables::FutexWaitable mutex;
ADestructionWatcher *pFirstWatcher {};
AuList<ADestructionWatcher *> listpWatches;
inline void RemoveWatcher(ADestructionWatcher *pWatcher);
inline void RemoveWatcherCall(ADestructionWatcher *pWatcher);
};
struct ADestructionWatcher
{
inline ADestructionWatcher();
inline ~ADestructionWatcher();
inline void Observe(DestructionWatch *pWatch);
inline bool IsObservedAlive();
inline bool IsObservedDead();
protected:
inline virtual void OnDestroyedChild()
{
}
private:
friend struct DestructionWatch;
inline void OnSelfDTOR();
inline void OnDTOR();
DestructionWatch *pParent {};
bool bWasCalled {};
};
DestructionWatch::DestructionWatch()
{
}
DestructionWatch::~DestructionWatch()
{
this->RemoveAll();
}
void DestructionWatch::RemoveAll()
{
AU_LOCK_GUARD(this->mutex);
if (auto pWatcher = AuExchange(this->pFirstWatcher, nullptr))
{
this->RemoveWatcherCall(pWatcher);
}
for (const auto pWatcher : AuExchange(this->listpWatches, {}))
{
this->RemoveWatcherCall(pWatcher);
}
}
void DestructionWatch::RemoveWatcher(ADestructionWatcher *pWatcher)
{
AU_LOCK_GUARD(this->mutex);
if (this->pFirstWatcher == pWatcher)
{
this->pFirstWatcher = nullptr;
}
AuTryRemove(this->listpWatches, pWatcher);
}
void DestructionWatch::RemoveWatcherCall(ADestructionWatcher *pWatcher)
{
pWatcher->OnDTOR();
}
ADestructionWatcher::ADestructionWatcher()
{
}
ADestructionWatcher::~ADestructionWatcher()
{
this->OnSelfDTOR();
}
void ADestructionWatcher::Observe(DestructionWatch *pWatch)
{
AU_LOCK_GUARD(pWatch->mutex);
if (!pWatch->pFirstWatcher)
{
pWatch->pFirstWatcher = this;
}
else
{
pWatch->listpWatches.push_back(this);
}
this->pParent = pWatch;
}
bool ADestructionWatcher::IsObservedAlive()
{
return !this->bWasCalled;
}
bool ADestructionWatcher::IsObservedDead()
{
return this->bWasCalled;
}
void ADestructionWatcher::OnSelfDTOR()
{
if (auto pParent = AuExchange(this->pParent, nullptr))
{
pParent->RemoveWatcher(this);
}
}
void ADestructionWatcher::OnDTOR()
{
this->pParent = nullptr;
if (AuExchange(this->bWasCalled, true))
{
return;
}
this->OnDestroyedChild();
}
}