[+] AuFutexBarrier

This commit is contained in:
Reece Wilson 2023-09-20 04:52:44 +01:00
parent 42a8218916
commit 7efde62c3c
3 changed files with 129 additions and 1 deletions

View File

@ -142,6 +142,7 @@ using AuBinarySemaphore = AuThreadPrimitives::Event;
using AuFutexMutex = AuThreading::Waitables::FutexWaitable;
using AuFutexSemaphore = AuThreading::Waitables::FutexSemaphoreWaitable;
using AuFutexCond = AuThreading::Waitables::FutexCondWaitable;
using AuFutexBarrier = AuThreading::Waitables::FutexBarrier;
using AuInitOnce = AuThreading::InitOnce;
using AuInitOnceSmall = __audetail::InitOnceABI;

View File

@ -0,0 +1,126 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FutexBarrier.hpp
Date: 2023-09-20
Author: Reece
***/
#pragma once
#include "../WakeOnAddress.hpp"
#include "../SpinTime.hpp"
namespace Aurora::Threading::Waitables
{
struct FutexBarrier final
{
inline constexpr FutexBarrier(AuUInt32 uExpectThreads) :
uAtomicSleeping(uExpectThreads),
uAtomicState(0)
{}
AU_NO_COPY_NO_MOVE(FutexBarrier);
inline bool Enter()
{
bool bTimeout {};
return this->Park(bTimeout, true, 0);
}
inline AuPair<bool /* bSuccess */, bool /* bTimeOut */>
EnterTimed(AuUInt64 uTimeoutAbsNS)
{
bool bTimeout {};
bool bSuccess = this->Park(bTimeout, true, uTimeoutAbsNS);
return AuMakePair(bSuccess, bTimeout);
}
inline bool TryEnter()
{
return this->TryEnterNoSpin();
}
inline bool TryWait()
{
return this->TryChkNoSpin();
}
inline bool Wait(AuUInt64 uTimeoutAbsNS = 0)
{
bool bTimeout {};
(void)this->Park(bTimeout, false, uTimeoutAbsNS);
return !bTimeout;
}
private:
auline bool Park(bool &bTimedOut, bool bTakeOwnership, AuUInt64 uTimeoutAbsNS)
{
static const AuUInt32 kRef { 0 };
bTimedOut = false;
if (bTakeOwnership)
{
if (!this->TryEnterNoSpin())
{
return false;
}
}
if (this->TryChkNoSpin())
{
return true;
}
(void)TryWaitOnAddress((const void *)&this->uAtomicState, &kRef, sizeof(kRef));
while (!this->TryChkNoSpin())
{
if (!WaitOnAddressSteady((const void *)&this->uAtomicState, &kRef, sizeof(kRef), uTimeoutAbsNS))
{
if (this->TryChkNoSpin())
{
return true;
}
else
{
bTimedOut = true;
return false;
}
}
}
return true;
}
auline bool TryEnterNoSpin()
{
AuUInt32 uState;
while ((uState = AuAtomicLoad(&this->uAtomicSleeping)) != 0)
{
if (AuAtomicCompareExchange(&this->uAtomicSleeping, uState - 1, uState) == uState)
{
if (uState == 1)
{
AuAtomicStore(&this->uAtomicState, 1u);
WakeAllOnAddress((const void *)&this->uAtomicState);
}
return true;
}
}
return false;
}
auline bool TryChkNoSpin()
{
return AuAtomicLoad(&this->uAtomicState) == 1;
}
public:
AuAUInt32 uAtomicState {};
AuAUInt32 uAtomicSleeping {};
};
}

View File

@ -11,4 +11,5 @@
#include "BooleanWaitable.hpp"
#include "FutexWaitable.hpp"
#include "FutexSemaphoreWaitable.hpp"
#include "FutexCondWaitable.hpp"
#include "FutexCondWaitable.hpp"
#include "FutexBarrier.hpp"