108 lines
4.0 KiB
C++
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};
|
|
};
|
|
} |