[+] LSLocalSemaphore (faster io semaphore)

This commit is contained in:
Reece Wilson 2023-10-21 04:57:25 +01:00
parent 1589079ead
commit 186444853d
4 changed files with 214 additions and 1 deletions

View File

@ -0,0 +1,172 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LSLocalSemaphore.cpp
Date: 2023-10-21
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "LSLocalSemaphore.hpp"
#include <Source/Threading/Primitives/SMTYield.hpp>
namespace Aurora::IO::Loop
{
static auto const kFutexBitWake = 256u;
LSLocalSemaphore::LSLocalSemaphore()
{
}
LSLocalSemaphore::~LSLocalSemaphore()
{
}
bool LSLocalSemaphore::TryInit(AuUInt32 initialCount)
{
if (!LSSemaphore::TryInit(1))
{
return false;
}
this->uAtomicSemaphore = initialCount;
return true;
}
bool LSLocalSemaphore::OnTrigger(AuUInt handle)
{
if (AuAtomicLoad(&this->uAtomicWord) & kFutexBitWake)
{
AuAtomicSub(&this->uAtomicWord, kFutexBitWake);
}
return this->TryTakeNoSpin();
}
bool LSLocalSemaphore::AddOne()
{
AuAtomicAdd(&this->uAtomicSemaphore, 1u);
while (true)
{
auto uState = AuAtomicLoad(&this->uAtomicWord);
if (uState & kFutexBitWake)
{
if (AuAtomicCompareExchange(&this->uAtomicWord, uState, uState) == uState)
{
return true;
}
else
{
continue;
}
}
if (AuAtomicCompareExchange(&this->uAtomicWord, uState + kFutexBitWake, uState) == uState)
{
LSSemaphore::AddOne();
return true;
}
}
}
bool LSLocalSemaphore::IsSignaled()
{
return this->TryTake();
}
bool LSLocalSemaphore::WaitOn(AuUInt32 timeout)
{
return this->TryTakeWaitMS(timeout);
}
ELoopSource LSLocalSemaphore::GetType()
{
return ELoopSource::eSourceSemaphore;
}
bool LSLocalSemaphore::TryTakeNoSpin()
{
AuUInt32 uOld {};
while ((uOld = this->uAtomicSemaphore))
{
if (AuAtomicCompareExchange(&this->uAtomicSemaphore, uOld - 1, uOld) == uOld)
{
return true;
}
}
return false;
}
bool LSLocalSemaphore::TryTakeSpin()
{
return Threading::Primitives::DoTryIf([&]
{
return this->TryTakeNoSpin();
});
}
bool LSLocalSemaphore::TryTake()
{
return this->TryTakeNoSpin();
}
bool LSLocalSemaphore::TryTakeWaitMS(AuUInt32 timeout)
{
auto uEndTime = AuTime::SteadyClockMS() + timeout;
if (this->TryTakeSpin())
{
return true;
}
while (!this->TryTakeNoSpin())
{
if (!timeout)
{
if (LSSemaphore::WaitOn(0))
{
return true;
}
}
else
{
auto uStartTime = Time::SteadyClockNS();
if (uStartTime >= uEndTime)
{
return false;
}
if (LSSemaphore::WaitOn(AuNSToMS<AuInt64>(uEndTime - uStartTime)))
{
return true;
}
}
}
return true;
}
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 initialCount)
{
auto pMutex = AuMakeShared<LSLocalSemaphore>();
if (!pMutex)
{
SysPushErrorGeneric();
return {};
}
if (!pMutex->TryInit(initialCount))
{
SysPushErrorNested();
return {};
}
return pMutex;
}
}

View File

@ -0,0 +1,37 @@
/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: LSLocalMutex.hpp
Date: 2023-10-21
Author: Reece
***/
#pragma once
#include "LSSemaphore.hpp"
namespace Aurora::IO::Loop
{
struct LSLocalSemaphore : LSSemaphore
{
LSLocalSemaphore();
~LSLocalSemaphore();
bool TryInit(AuUInt32 initialCount);
bool IsSignaled() override;
bool WaitOn(AuUInt32 timeout) override;
ELoopSource GetType() override;
bool AddOne() override;
virtual bool OnTrigger(AuUInt handle) override;
bool TryTakeNoSpin();
bool TryTakeSpin();
bool TryTake();
bool TryTakeWaitMS(AuUInt32 timeout);
AuAUInt32 uAtomicWord {};
AuAUInt32 uAtomicSemaphore {};
};
}

View File

@ -43,7 +43,7 @@ namespace Aurora::IO::Loop
bool LSSemaphore::TryInit(AuUInt32 initialCount)
{
this->Init(initialCount);
return this->handle != -1;
return this->HasValidHandle();
}
bool LSSemaphore::IsSignaledNonblocking()
@ -85,6 +85,7 @@ namespace Aurora::IO::Loop
return ELoopSource::eSourceSemaphore;
}
#if 0
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 initialCount)
{
auto pSemaphore = AuMakeShared<LSSemaphore>(initialCount);
@ -100,4 +101,5 @@ namespace Aurora::IO::Loop
return pSemaphore;
}
#endif
}

View File

@ -57,6 +57,7 @@ namespace Aurora::IO::Loop
return true;
}
#if 0
AUKN_SYM AuSPtr<ILSSemaphore> NewLSSemaphore(AuUInt32 initialCount)
{
AuSPtr<LSSemaphore> ret;
@ -70,4 +71,5 @@ namespace Aurora::IO::Loop
return AuMakeShared<LSSemaphore>(semaphore);
}
#endif
}