[*/+] Added internal AuLoop::WaitMultipleOrObjects function for POSIX Issue4+ users, excluding the BSDs, to optimize AuLoop::WaitForMultipleObject users. (Win32 and Xbox emulators).
This mitigates the epoll allocation / release under Linux.
This commit is contained in:
parent
67c4cdbee0
commit
5947e6a2c3
@ -7,8 +7,194 @@
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include "Loop.Unix.hpp"
|
||||
#include "ILoopSourceEx.hpp"
|
||||
#include <poll.h>
|
||||
|
||||
namespace Aurora::IO::Loop
|
||||
{
|
||||
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, bool bZeroTick, AuUInt32 dwTimeoutReq, bool bAllowOthers, bool &bTooMany)
|
||||
{
|
||||
#if defined(AURORA_HAS_NO_POSIX_POLL)
|
||||
// do the WinNT falllback into loop queue.
|
||||
//
|
||||
// loop queues should have long term persistency in a user-space ABI (kqueue) or in the kernel (epoll)
|
||||
// they may take longer to setup, may seem wasteful to create and throw away, but it's probably the best we can do under BSD kernels.
|
||||
// why? kevents exist for posix aio objects. they dont use fds.
|
||||
//
|
||||
// BSDs with posix AIO based async file transactions, >2.2 linux kernels, macos with corefoundation interop with kqueues, and other posix kernels with alternative aio will probably need
|
||||
// need to use the win32 64 <= handles path.
|
||||
bTooMany = true;
|
||||
return false;
|
||||
#else
|
||||
AuList<AuSPtr<ILoopSourceEx>> loopSourceExs;
|
||||
AuList<AuSPtr<ILoopSourceEx>> loopSourceExs2;
|
||||
AuList<AuSPtr<ILoopSource>> triggered;
|
||||
AuList<pollfd> handleArray;
|
||||
AuList<AuPair<AuUInt, bool>> handleIndicies;
|
||||
|
||||
try
|
||||
{
|
||||
loopSourceExs.reserve(objects.size());
|
||||
loopSourceExs2.reserve(objects.size());
|
||||
handleArray.reserve(objects.size());
|
||||
triggered.reserve(triggered.size());
|
||||
handleIndicies.reserve(triggered.size());
|
||||
|
||||
for (const auto &source : objects)
|
||||
{
|
||||
if (!source)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto extended = AuDynamicCast<ILoopSourceEx>(source))
|
||||
{
|
||||
loopSourceExs2.push_back(extended);
|
||||
|
||||
if (extended->Singular())
|
||||
{
|
||||
auto handle = extended->GetHandle();
|
||||
auto handleWrite = extended->GetWriteHandle();
|
||||
|
||||
auto i = loopSourceExs.size();
|
||||
loopSourceExs.push_back(extended);
|
||||
|
||||
if (handle != -1)
|
||||
{
|
||||
pollfd poll;
|
||||
poll.fd = handle;
|
||||
poll.events = POLLIN;
|
||||
poll.revents = 0;
|
||||
|
||||
handleArray.push_back(poll);
|
||||
handleIndicies.push_back(AuMakePair(i, false));
|
||||
}
|
||||
|
||||
if (handleWrite != -1)
|
||||
{
|
||||
pollfd poll;
|
||||
poll.fd = handleWrite;
|
||||
poll.events = POLLOUT;
|
||||
poll.revents = 0;
|
||||
|
||||
handleArray.push_back(poll);
|
||||
handleIndicies.push_back(AuMakePair(i, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto handles = extended->GetHandles();
|
||||
auto handlesWrite = extended->GetWriteHandles();
|
||||
|
||||
auto i = loopSourceExs.size();
|
||||
loopSourceExs.push_back(extended);
|
||||
|
||||
for (const auto &handle : handles)
|
||||
{
|
||||
pollfd poll;
|
||||
if (handle == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
poll.fd = handle;
|
||||
poll.events = POLLIN;
|
||||
poll.revents = 0;
|
||||
|
||||
handleArray.push_back(poll);
|
||||
handleIndicies.push_back(AuMakePair(i, false));
|
||||
}
|
||||
|
||||
for (const auto &handle : handlesWrite)
|
||||
{
|
||||
pollfd poll;
|
||||
if (handle == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
poll.fd = handle;
|
||||
poll.events = POLLOUT;
|
||||
poll.revents = 0;
|
||||
|
||||
handleArray.push_back(poll);
|
||||
handleIndicies.push_back(AuMakePair(i, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const auto &source : loopSourceExs2)
|
||||
{
|
||||
source->OnPresleep();
|
||||
}
|
||||
|
||||
AuUInt32 uTimeout {};
|
||||
if (bZeroTick)
|
||||
{
|
||||
uTimeout = 0;
|
||||
}
|
||||
else if (!dwTimeoutReq)
|
||||
{
|
||||
uTimeout = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uTimeout = dwTimeoutReq;
|
||||
}
|
||||
|
||||
int ret;
|
||||
do
|
||||
{
|
||||
ret = poll(handleArray.data(), handleArray.size(), uTimeout);
|
||||
uTimeout = 0;
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
for (AU_ITERATE_N(i, handleArray.size()))
|
||||
{
|
||||
if (!handleArray[i].revents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto uIndex = AuGet<0>(handleIndicies[i]);
|
||||
auto bRead = AuGet<1>(handleIndicies[i]);
|
||||
auto pLoopSource = AuExchange(loopSourceExs[uIndex], nullptr);
|
||||
if (!pLoopSource)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!pLoopSource->OnTrigger(handleArray[i].fd))
|
||||
{
|
||||
loopSourceExs[uIndex] = pLoopSource;
|
||||
continue;
|
||||
}
|
||||
|
||||
triggered.push_back(pLoopSource);
|
||||
|
||||
if (!bAllowOthers)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (ret == -1 &&
|
||||
errno == EINTR);
|
||||
|
||||
for (const auto &source : loopSourceExs2)
|
||||
{
|
||||
source->OnFinishSleep();
|
||||
}
|
||||
|
||||
return triggered;
|
||||
#endif
|
||||
}
|
||||
}
|
@ -53,7 +53,7 @@ namespace Aurora::IO::Loop
|
||||
return workerPid.GetPool()->WorkerToLoopSource(workerPid);
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED) || defined(AURORA_IS_POSIX_DERIVED)
|
||||
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, bool bZeroTick, AuUInt32 timeout, bool bAllowOthers, bool &bTooMany);
|
||||
#endif
|
||||
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjectsFallback(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout, bool bZeroTick, bool bAllowOthers, bool &bTimeout);
|
||||
@ -402,6 +402,15 @@ namespace Aurora::IO::Loop
|
||||
false;
|
||||
}
|
||||
else
|
||||
#elif defined(AURORA_IS_POSIX_DERIVED)
|
||||
if (true)
|
||||
{
|
||||
signaled = WaitMultipleOrObjects(lsList2, bZeroTick, uTimeoutMS, bAllowOthers, bTooMany);
|
||||
bTimedout = uTimeoutEnd && uTimeoutMS && !bZeroTick ?
|
||||
Time::SteadyClockNS() >= uTimeoutEnd :
|
||||
false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bTooMany = true;
|
||||
|
Loading…
Reference in New Issue
Block a user