[*] AuAsync build regression

[*] Fix potential for null deref under net adapters api
[*] Improved generic IO WaitFor * AND * (still suxs)
This commit is contained in:
Reece Wilson 2024-10-09 01:58:18 +01:00
parent f93181b0bf
commit 82ed6e5617
7 changed files with 152 additions and 68 deletions

View File

@ -703,6 +703,10 @@ namespace __detail
#endif #endif
#endif #endif
#if defined(AU_LANG_CPP_20) && !defined(AU_NO_COROUTINES)
#define AU_HasCoRoutineTraitsAvailable
#endif
#if defined(AU_NO_COROUTINES) || ((defined(AURORA_COMPILER_MSVC) && defined(AU_LANG_CPP_14)) || (defined(AURORA_COMPILER_CLANG) && defined(AU_LANG_CPP_14)) || (defined(AURORA_COMPILER_CLANG) && defined(AU_LANG_CPP_17)) || (defined(AURORA_COMPILER_MSVC) && !defined(_RESUMABLE_FUNCTIONS_SUPPORTED))) #if defined(AU_NO_COROUTINES) || ((defined(AURORA_COMPILER_MSVC) && defined(AU_LANG_CPP_14)) || (defined(AURORA_COMPILER_CLANG) && defined(AU_LANG_CPP_14)) || (defined(AURORA_COMPILER_CLANG) && defined(AU_LANG_CPP_17)) || (defined(AURORA_COMPILER_MSVC) && !defined(_RESUMABLE_FUNCTIONS_SUPPORTED)))
#elif defined(AU_HasCoRoutinedIncluded) #elif defined(AU_HasCoRoutinedIncluded)

View File

@ -134,6 +134,7 @@ namespace Aurora::IO::Loop
if (lsList.size() == 1) if (lsList.size() == 1)
{ {
AuUInt8 uFlags {};
auto pSource = lsList[0]; auto pSource = lsList[0];
if (!pSource) if (!pSource)
{ {
@ -141,18 +142,23 @@ namespace Aurora::IO::Loop
return true; return true;
} }
if (!bSpin)
{
uFlags = kFlagLSTryNoSpin;
}
bool bStatus {}; bool bStatus {};
if (bSleepForever) if (bSleepForever)
{ {
bStatus = pSource->WaitOn(0); bStatus = pSource->WaitOnExt(uFlags, 0);
} }
else if (bHasTimeOut) else if (bHasTimeOut)
{ {
bStatus = pSource->WaitOn(optTimeoutMS.value()); bStatus = pSource->WaitOnExt(uFlags, optTimeoutMS.value());
} }
else else
{ {
bStatus = pSource->IsSignaled(); bStatus = pSource->IsSignaledExt(uFlags);
} }
if (bStatus) if (bStatus)
@ -173,6 +179,8 @@ namespace Aurora::IO::Loop
if (!bAny) if (!bAny)
{ {
AuUInt32 uStartingOffset { 1 };
auto &entryZero = lsList[0]; auto &entryZero = lsList[0];
if (!entryZero) if (!entryZero)
@ -183,25 +191,32 @@ namespace Aurora::IO::Loop
if (entryZero) if (entryZero)
{ {
bool bStatus {}; bool bStatus {};
auto eType = entryZero->GetType();
AuUInt8 uFlags {};
if (bSleepForever) if (!bSpin)
{ {
bStatus = entryZero->WaitOn(0); uFlags = kFlagLSTryNoSpin;
}
if (eType == ELoopSource::eSourceMutex ||
eType == ELoopSource::eSourceFastMutex)
{
bStatus = false;
uStartingOffset = 0;
goto mainAllSleep;
}
else if (bSleepForever)
{
bStatus = entryZero->WaitOnExt(uFlags, 0);
} }
else if (bHasTimeOut) else if (bHasTimeOut)
{ {
bStatus = entryZero->WaitOn(optTimeoutMS.value()); bStatus = entryZero->WaitOnExt(uFlags, optTimeoutMS.value());
}
else if (bSpin)
{
bStatus = entryZero->IsSignaled();
} }
else else
{ {
auto pSourceEx = AuDynamicCast<Loop::ILoopSourceEx>(entryZero); bStatus = entryZero->IsSignaledExt(uFlags);
bStatus = pSourceEx ?
pSourceEx->IsSignaledNoSpinIfUserland() :
entryZero->IsSignaled();
} }
if (!bStatus) if (!bStatus)
@ -215,66 +230,99 @@ namespace Aurora::IO::Loop
} }
} }
if (lsList.size() > 1 && mainAllSleep:
if (lsList.size() > uStartingOffset &&
(!bAvoidKrn || signaled.empty())) (!bAvoidKrn || signaled.empty()))
{ {
for (AU_ITERATE_N_TO_X(i, 1, lsList.size())) for (AU_ITERATE_N(a, 2))
{ {
AuUInt32 uTimeoutMS {}; bool dBreak {};
if (uTimeoutEnd) for (AU_ITERATE_N_TO_X(i, uStartingOffset, lsList.size()))
{ {
auto uStartTime = Time::SteadyClockNS(); AuUInt32 uTimeoutMS {};
if (uStartTime >= uTimeoutEnd) bool bIsMutex {};
{ ELoopSource eType;
#if 0
break;
#else
bZeroTick = true;
#endif
}
uTimeoutMS = AuNSToMS<AuInt64>(uTimeoutEnd - uStartTime); auto &pCurrent = lsList[i];
if (!uTimeoutMS)
{
#if 0
break;
#else
bZeroTick = true;
#endif
}
}
if (bZeroTick) eType = pCurrent->GetType();
{ bIsMutex = eType == ELoopSource::eSourceMutex ||
if (bSpin) eType == ELoopSource::eSourceFastMutex;
if (bIsMutex ^ bool(a))
{ {
if (!lsList[i]->IsSignaled()) continue;
}
if (uTimeoutEnd && !bZeroTick)
{
auto uStartTime = Time::SteadyClockNS();
if (uStartTime >= uTimeoutEnd)
{ {
break; bZeroTick = true;
}
uTimeoutMS = AuNSToMS<AuInt64>(uTimeoutEnd - uStartTime);
if (!uTimeoutMS)
{
bZeroTick = true;
}
}
if (bZeroTick)
{
if (bSpin)
{
if (!pCurrent->IsSignaled())
{
dBreak = true;
break;
}
bSpin = false;
}
else
{
if (!pCurrent->IsSignaledExt(kFlagLSTryNoSpin))
{
dBreak = true;
break;
}
} }
} }
else else
{ {
auto pSourceEx = AuDynamicCast<Loop::ILoopSourceEx>(lsList[i]); if (bSpin)
if (!(pSourceEx ?
pSourceEx->IsSignaledNoSpinIfUserland() :
entryZero->IsSignaled()))
{ {
break; if (!pCurrent->WaitOnAbs(uTimeoutEnd))
{
dBreak = true;
break;
}
// TBD
bSpin = false;
}
else
{
if (!pCurrent->WaitOnAbsExt(kFlagLSTryNoSpin, uTimeoutEnd))
{
dBreak = true;
break;
}
} }
} }
}
else reverseList.push_back(i);
{ signaled.push_back(pCurrent);
if (!lsList[i]->WaitOn(uTimeoutMS))
{
break;
}
} }
reverseList.push_back(i); if (dBreak || signaled.size() != lsList.size())
signaled.push_back(lsList[i]); {
break;
}
} }
} }
@ -328,12 +376,9 @@ namespace Aurora::IO::Loop
eType == ELoopSource::eSourceFastSemaphore || eType == ELoopSource::eSourceFastSemaphore ||
eType == ELoopSource::eSourceFastEvent) eType == ELoopSource::eSourceFastEvent)
{ {
auto pSourceEx = AuDynamicCast<Loop::ILoopSourceEx>(pSource);
bAnyFound = true; bAnyFound = true;
if ((pSourceEx && pSourceEx->IsSignaledNoSpinIfUserland()) || if (pSource->IsSignaledExt(kFlagLSTryNoSpin))
(!pSourceEx && pSource->IsSignaled()))
{ {
signalTemp.push_back(pSource); signalTemp.push_back(pSource);
itr = lsList2.erase(itr); itr = lsList2.erase(itr);

View File

@ -17,7 +17,7 @@ namespace Aurora::IO::Loop
bool WaitSingleBase::IsSignaled() bool WaitSingleBase::IsSignaled()
{ {
return this->IsSignaledExt(0); return WaitSingleBase::IsSignaledExt(0);
} }
bool WaitSingleBase::IsSignaledExt(AuUInt8 uFlags) bool WaitSingleBase::IsSignaledExt(AuUInt8 uFlags)
@ -75,7 +75,7 @@ namespace Aurora::IO::Loop
bool WaitSingleBase::WaitOn(AuUInt32 timeout) bool WaitSingleBase::WaitOn(AuUInt32 timeout)
{ {
return this->WaitOnExt(0, timeout); return WaitSingleBase::WaitOnExt(0, timeout);
} }
bool WaitSingleBase::WaitOnExt(AuUInt8 uFlags, AuUInt32 timeout) bool WaitSingleBase::WaitOnExt(AuUInt8 uFlags, AuUInt32 timeout)
@ -96,12 +96,12 @@ namespace Aurora::IO::Loop
AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(timeout) : AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(timeout) :
0; 0;
return this->WaitOnAbsExt(uFlags, uEndTime); return WaitSingleBase::WaitOnAbsExt(uFlags, uEndTime);
} }
bool WaitSingleBase::WaitOnAbs(AuUInt64 uTimeoutAbs) bool WaitSingleBase::WaitOnAbs(AuUInt64 uTimeoutAbs)
{ {
return this->WaitOnAbsExt(0, uTimeoutAbs); return WaitSingleBase::WaitOnAbsExt(0, uTimeoutAbs);
} }
bool WaitSingleBase::WaitOnAbsExt(AuUInt8 uFlags, AuUInt64 uEndTime) bool WaitSingleBase::WaitOnAbsExt(AuUInt8 uFlags, AuUInt64 uEndTime)

View File

@ -239,9 +239,16 @@ namespace Aurora::IO::Net
adapter.uReceiveBytesPerSec = pCurrAddresses->ReceiveLinkSpeed / 8; adapter.uReceiveBytesPerSec = pCurrAddresses->ReceiveLinkSpeed / 8;
} }
if (adapter.address.Value().ip == EIPProtocol::eIPProtocolV4) if (adapter.address)
{ {
adapter.index = pCurrAddresses->IfIndex; if (adapter.address.Value().ip == EIPProtocol::eIPProtocolV4)
{
adapter.index = pCurrAddresses->IfIndex;
}
else
{
adapter.index = adaptersOut.size();
}
} }
else else
{ {

View File

@ -63,6 +63,10 @@ namespace Aurora::IO::Net
AuSPtr<NetWorker> NetSrvWorkers::GetWorkerByIndex(AuUInt index) AuSPtr<NetWorker> NetSrvWorkers::GetWorkerByIndex(AuUInt index)
{ {
AU_LOCK_GUARD(this->mutex_); AU_LOCK_GUARD(this->mutex_);
if (this->workerPool_.empty())
{
return {};
}
return this->workerPool_[index % this->workerPool_.size()]; return this->workerPool_[index % this->workerPool_.size()];
} }

View File

@ -180,7 +180,31 @@ namespace Aurora::Threading
{ {
if (releasedObjects[i]) if (releasedObjects[i])
{ {
waitables[i]->Unlock(); AuUInt uHandle(0);
if (!waitables[i]->HasOSHandle(uHandle) &&
uHandle == 0xFF69421)
{
// Autoreset events
// In 2020/2021, I didn't want semaphore and mutex behaviour in event iwaitable::unlock()
// The logic:
//
// AU_LOCK_GUARD(gMutex) makes sense
//
// Semaphore gSemaphore(1); // a mutex
// AU_LOCK_GUARD(gSemaphore) can make sense in academic theory only
//
// AU_LOCK_GUARD(gResetEvent) does not sense.
// in the condvar pattern, the signaling thread does the unlock.
//
// ...therefore, the ::Unlock() should not be event setters.
AuStaticCast<AuThreadPrimitives::IEvent>(waitables[i])->Set();
}
else
{
// Semaphores and Mutexes
waitables[i]->Unlock();
}
} }
} }
} }

View File

@ -297,7 +297,7 @@ namespace Aurora::Threading::Primitives
bool EventImpl::HasOSHandle(AuMach &mach) bool EventImpl::HasOSHandle(AuMach &mach)
{ {
mach = 0; mach = this->bAtomicRelease_ ? 0xFF69421 : 0;
return false; return false;
} }