[+] LSLocalSemaphore (faster io semaphore)
This commit is contained in:
parent
1589079ead
commit
186444853d
172
Source/IO/Loop/LSLocalSemaphore.cpp
Normal file
172
Source/IO/Loop/LSLocalSemaphore.cpp
Normal 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;
|
||||
}
|
||||
}
|
37
Source/IO/Loop/LSLocalSemaphore.hpp
Normal file
37
Source/IO/Loop/LSLocalSemaphore.hpp
Normal 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 {};
|
||||
};
|
||||
}
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user