[*/+] 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 <Source/RuntimeInternal.hpp>
|
||||||
#include "Loop.Unix.hpp"
|
#include "Loop.Unix.hpp"
|
||||||
|
#include "ILoopSourceEx.hpp"
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
namespace Aurora::IO::Loop
|
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);
|
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);
|
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjects(const AuList<AuSPtr<ILoopSource>> &objects, bool bZeroTick, AuUInt32 timeout, bool bAllowOthers, bool &bTooMany);
|
||||||
#endif
|
#endif
|
||||||
AuList<AuSPtr<ILoopSource>> WaitMultipleOrObjectsFallback(const AuList<AuSPtr<ILoopSource>> &objects, AuUInt32 timeout, bool bZeroTick, bool bAllowOthers, bool &bTimeout);
|
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;
|
false;
|
||||||
}
|
}
|
||||||
else
|
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
|
#endif
|
||||||
{
|
{
|
||||||
bTooMany = true;
|
bTooMany = true;
|
||||||
|
Loading…
Reference in New Issue
Block a user