[+] 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:
parent
e366d058f6
commit
60bb1020ce
@ -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
|
||||
{
|
||||
|
@ -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 {};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -88,4 +88,6 @@ namespace Aurora::IO
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AUKN_SYM AuUInt32 WaitMultipleLoopSources(const AuList<AuSPtr<Loop::ILoopSource>> &lsList, bool bAny, AuOptionalEx<AuUInt32> uTimeoutMS);
|
||||
}
|
Loading…
Reference in New Issue
Block a user