AuroraRuntime/Source/Loop/LoopQueue.NT.hpp

108 lines
4.0 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LoopQueue.NT.hpp
Date: 2022-2-1W2
Author: Reece
***/
#pragma once
#include "ILoopSourceEx.hpp"
namespace Aurora::Loop
{
struct LoopQueue : ILoopQueue
{
LoopQueue();
~LoopQueue();
bool SourceAdd(const AuSPtr<ILoopSource> &source) override;
bool SourceAddWithTimeout(const AuSPtr<ILoopSource> &source, AuUInt32 ms) override;
bool SourceRemove(const AuSPtr<ILoopSource> &source) override;
AuUInt32 GetSourceCount() override;
virtual bool AddCallback(const AuSPtr<ILoopSource> &source, const AuSPtr<ILoopSourceSubscriber> &subscriber) override;
virtual bool AddCallbackEx(const AuSPtr<ILoopSource> &source, const AuSPtr<ILoopSourceSubscriberEx> &subscriber) override;
virtual bool AddCallback(const AuSPtr<ILoopSourceSubscriber> &subscriber) override;
void ChugPathConfigure(AuUInt32 sectionTickTime, AuSInt sectionDequeCount) override;
void ChugHint(bool value) override;
virtual bool Commit() override;
bool HasFinished() override;
bool IsSignaled() override;
bool WaitAll(AuUInt32 timeout) override;
AuUInt32 WaitAny(AuUInt32 timeout) override;
AuList<AuSPtr<ILoopSource>> WaitAnyEx(AuUInt32 timeout) override;
void Sync();
void Unlock();
private:
void ConsiderEvicitingTimeoutsAll();
struct ExtendeSourceInfo
{
inline ExtendeSourceInfo(AuSPtr<ILoopSourceEx> in) : source(in)
{}
AuSPtr<ILoopSourceEx> source;
AuSPtr<ILoopSource> sourceBase;
AuThreadPrimitives::SpinLock lock; // im too brain dead to think of a solution to the AddCallback thread safety issue, so i'm going to optimize Wait[...]s subscriber lookup with filtered ccaches in here, protected by this spinlock
AuList<AuSPtr<ILoopSourceSubscriber>> globalSubscribers;
AuList<AuSPtr<ILoopSourceSubscriber>> specificSubscribers;
AuList<AuSPtr<ILoopSourceSubscriberEx>> timeoutSubscribers;
AuUInt32 timeoutAbs;
bool ConsiderTimeout() const
{
if ((timeoutAbs) && (AuTime::CurrentInternalClockMS() >= timeoutAbs))
{
for (const auto &handler : timeoutSubscribers)
{
try
{
handler->OnTimeout(sourceBase);
}
catch (...)
{
SysPushErrorCatch();
}
}
return true;
}
return false;
}
};
bool IsValid();
void RemoveSourceNB(const AuSPtr<ILoopSource> &source, bool removeHandles);
bool WaitAnyNBSpurious(AuUInt32 timeout, AuUInt32 &chuggerIndex, AuList<AuSPtr<ILoopSource>> *trigger, bool poll);
bool ChugWaitAny(AuUInt32 timeout, AuUInt32 &chuggerIndex, AuUInt32 &offset);
//
AuList<AuSPtr<ILoopSourceSubscriber>> msgCallbacks_;
AuList<AuSPtr<ILoopSource>> removedSources_;
AuThreadPrimitives::SpinLock sourceMutex_;
AuList<AuTuple<AuSPtr<ILoopSource>, AuUInt32>> sources_;
//
// OS Cache
AuThreadPrimitives::RWLockUnique_t rwMutex_ = AuThreadPrimitives::RWLockUnique();
bool bIsWinLoop_ {};
bool bIsThreadSafe_ {};
AuList<HANDLE> handleArray_;
AuUInt32 slowTickMs_ {1};
AuUInt32 slowTickRate_ {MAXIMUM_WAIT_OBJECTS};
bool forceChug_ {};
AuList<ExtendeSourceInfo> loopSourceExs_;
AuSPtr<ILoopSource> msgSource_;
HANDLE hEvent_ {INVALID_HANDLE_VALUE};
};
}