[+] bool WaitMultipleLoopSources(const AuList<AuSPtr<Loop::ILoopSource>> &lsList,

AuList<AuSPtr<Loop::ILoopSource>> &signaled,
                                 bool bAny = true,
                                 AuOptionalEx<AuUInt32> uTimeoutMS = 0);
This commit is contained in:
Reece Wilson 2023-10-21 06:10:33 +01:00
parent e366d058f6
commit 60bb1020ce
5 changed files with 244 additions and 7 deletions

View File

@ -19,8 +19,10 @@
namespace Aurora::IO::Loop
{
/// @deprecated
AUKN_SYM AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout);
AUKN_SYM bool WaitMultipleLoopSources(const AuList<AuSPtr<Loop::ILoopSource>> &lsList,
AuList<AuSPtr<Loop::ILoopSource>> &signaled,
bool bAny = true,
AuOptionalEx<AuUInt32> uTimeoutMS = 0);
struct ILSSemaphore : virtual ILoopSource
{

View File

@ -12,7 +12,7 @@
namespace Aurora::IO::Loop
{
AUKN_SYM AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout)
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout)
{
bool isWinLoop;
AuList<AuSPtr<ILoopSourceEx>> loopSourceExs;
@ -96,7 +96,6 @@ namespace Aurora::IO::Loop
for (const auto &source : loopSourceExs)
{
if (!error)
{
AuUInt lastHandle {};

View File

@ -7,6 +7,7 @@
***/
#include <Source/RuntimeInternal.hpp>
#include "Loop.hpp"
#include "ILoopSourceEx.hpp"
namespace Aurora::IO::Loop
{
@ -49,4 +50,237 @@ namespace Aurora::IO::Loop
return workerPid.pool->WorkerToLoopSource(workerPid);
}
#if defined(AURORA_PLATFORM_WIN32)
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout);
#endif
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjectsFallback(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout, bool &bTimeout);
void ResetLoopSourceFalseAlarm(const AuSPtr<Loop::ILoopSource> &pLoopSource)
{
if (!pLoopSource)
{
return;
}
if (pLoopSource->GetType() == ELoopSource::eSourceWin32)
{
return;
}
if (auto pMutex = AuDynamicCast<Loop::ILSMutex>(pLoopSource))
{
pMutex->Unlock();
return;
}
if (auto pSemaphore = AuDynamicCast<Loop::ILSSemaphore>(pLoopSource))
{
pSemaphore->AddOne();
return;
}
if (auto pEvent = AuDynamicCast<Loop::ILSEvent>(pLoopSource))
{
pEvent->Set();
return;
}
}
AUKN_SYM bool WaitMultipleLoopSources(const AuList<AuSPtr<Loop::ILoopSource>> &lsList,
AuList<AuSPtr<Loop::ILoopSource>> &signaled,
bool bAny,
AuOptionalEx<AuUInt32> uTimeoutMS)
{
AU_DEBUG_MEMCRUNCH;
signaled.clear();
AuList<AuUInt32> reverseList;
if (lsList.empty())
{
return true;
}
auto uTimeoutEnd = uTimeoutMS ?
AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(uTimeoutMS) :
0;
signaled.reserve(lsList.size());
if (!bAny)
{
AuSPtr<Loop::ILoopQueue> pQueue;
auto &entryZero = lsList[0];
if (!entryZero)
{
signaled.push_back({});
}
if (entryZero)
{
if (!entryZero->WaitOn(uTimeoutMS))
{
goto next;
}
else
{
reverseList.push_back(0);
signaled.push_back(entryZero);
}
}
if (lsList.size() > 1)
{
pQueue = AuLoop::NewLoopQueue();
if (!pQueue)
{
goto next;
}
for (AU_ITERATE_N_TO_X(i, 1, lsList.size()))
{
AuUInt32 uTimeoutMS {};
if (uTimeoutEnd)
{
auto uStartTime = Time::SteadyClockNS();
if (uStartTime >= uTimeoutEnd)
{
break;
}
uTimeoutMS = AuNSToMS<AuInt64>(uTimeoutEnd - uStartTime);
if (!uTimeoutMS)
{
break;
}
}
if (!lsList[i]->WaitOn(uTimeoutMS))
{
break;
}
reverseList.push_back(i);
signaled.push_back(lsList[i]);
}
}
next:
bool bReturnStatus { true };
if (signaled.size() != lsList.size())
{
bReturnStatus = false;
signaled.clear();
for (const auto &uIndex : reverseList)
{
ResetLoopSourceFalseAlarm(lsList[uIndex]);
}
}
return bReturnStatus;
}
else
{
bool bTimeout {};
signaled = WaitMultipleOrObjectsFallback(lsList, uTimeoutMS, bTimeout);
if (bTimeout)
{
return false;
}
return true;
}
}
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjectsFallback(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout, bool &bTimeout)
{
AuList<AuSPtr<ILoopSourceEx>> loopSourceExs;
AuList<AuSPtr<ILoopSource>> triggered;
bTimeout = false;
auto pQueue = AuLoop::NewLoopQueue();
if (!pQueue)
{
return {};
}
try
{
loopSourceExs.reserve(objects.size());
triggered.reserve(triggered.size());
for (const auto &source : objects)
{
if (!source)
{
continue;
}
if (!pQueue->SourceAdd(source))
{
return {};
}
if (source->GetType() == ELoopSource::eSourceWin32)
{
continue;
}
if (auto extended = AuDynamicCast<ILoopSourceEx>(source))
{
if (!AuTryInsert(loopSourceExs, extended))
{
return {};
}
}
}
}
catch (...)
{
return {};
}
auto pListener = AuMakeSharedThrow<AuLoop::ILoopSourceSubscriberFunctional>([&](const AuSPtr<ILoopSource> &source)
{
AU_DEBUG_MEMCRUNCH;
triggered.push_back(source);
return false;
});
if (!pQueue->AddCallback(pListener))
{
return {};
}
for (const auto &source : loopSourceExs)
{
source->OnPresleep();
}
bTimeout = !pQueue->WaitAny(timeout);
for (AU_ITERATE_N(i, objects.size()))
{
auto source = loopSourceExs[i];
if (std::find(triggered.begin(), triggered.end(), source) == triggered.end())
{
if (source->IsSignaled())
{
triggered.push_back(source);
}
}
source->OnFinishSleep();
}
return triggered;
}
}

View File

@ -88,4 +88,6 @@ namespace Aurora::IO
{
}
AUKN_SYM AuUInt32 WaitMultipleLoopSources(const AuList<AuSPtr<Loop::ILoopSource>> &lsList, bool bAny, AuOptionalEx<AuUInt32> uTimeoutMS);
}