[+] LSLocalEvent
This commit is contained in:
parent
f0aef1f712
commit
f185f13dc7
@ -111,6 +111,7 @@ namespace Aurora::IO::Loop
|
||||
return ELoopSource::eSourceEvent;
|
||||
}
|
||||
|
||||
#if 0
|
||||
AUKN_SYM AuSPtr<ILSEvent> NewLSEvent(bool triggered, bool atomicRelease, bool permitMultipleTriggers)
|
||||
{
|
||||
auto event = AuMakeShared<LSEvent>(triggered, atomicRelease, permitMultipleTriggers);
|
||||
@ -126,4 +127,5 @@ namespace Aurora::IO::Loop
|
||||
|
||||
return event;
|
||||
}
|
||||
#endif
|
||||
}
|
@ -54,6 +54,7 @@ namespace Aurora::IO::Loop
|
||||
return ELoopSource::eSourceEvent;
|
||||
}
|
||||
|
||||
#if 0
|
||||
AUKN_SYM AuSPtr<ILSEvent> NewLSEvent(bool triggerd, bool atomicRelease, bool permitMultipleTriggers)
|
||||
{
|
||||
AuSPtr<LSEvent> ret;
|
||||
@ -70,4 +71,5 @@ namespace Aurora::IO::Loop
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
259
Source/IO/Loop/LSLocalEvent.cpp
Normal file
259
Source/IO/Loop/LSLocalEvent.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSLocalEvent.cpp
|
||||
Date: 2023-10-21
|
||||
Author: Reece
|
||||
***/
|
||||
#include <RuntimeInternal.hpp>
|
||||
#include "LSLocalEvent.hpp"
|
||||
#include <Source/Threading/Primitives/SMTYield.hpp>
|
||||
|
||||
namespace Aurora::IO::Loop
|
||||
{
|
||||
LSLocalEvent::LSLocalEvent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LSLocalEvent::~LSLocalEvent()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool LSLocalEvent::TryInit(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers)
|
||||
{
|
||||
if (!LSSemaphore::TryInit(1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this->bTriggered_ = bTriggered;
|
||||
this->bAtomicRelease_ = bAtomicRelease;
|
||||
this->bPermitMultipleTriggers_= bPermitMultipleTriggers;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LSLocalEvent::OnTrigger(AuUInt handle)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
EventBits bits;
|
||||
bits.state = AuAtomicLoad(&this->state_);
|
||||
|
||||
if (bits.bAtomicRelease)
|
||||
{
|
||||
if (bits.bTriggered)
|
||||
{
|
||||
auto next = bits;
|
||||
next.bTriggered = 0;
|
||||
|
||||
if (AuAtomicCompareExchange(&this->state_, next.state, bits.state) != bits.state)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits.bTriggered)
|
||||
{
|
||||
LSSemaphore::AddOne();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LSLocalEvent::IsSignaled()
|
||||
{
|
||||
return this->TryTake();
|
||||
}
|
||||
|
||||
bool LSLocalEvent::WaitOn(AuUInt32 timeout)
|
||||
{
|
||||
return this->TryTakeWaitMS(timeout);
|
||||
}
|
||||
|
||||
ELoopSource LSLocalEvent::GetType()
|
||||
{
|
||||
return ELoopSource::eSourceEvent;
|
||||
}
|
||||
|
||||
bool LSLocalEvent::Set()
|
||||
{
|
||||
EventBits bits, next;
|
||||
|
||||
while (true)
|
||||
{
|
||||
bits.state = AuAtomicLoad(&this->state_);
|
||||
|
||||
if (!bits.bPermitMultipleTriggers)
|
||||
{
|
||||
if (bits.bTriggered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
next.state = bits.state;
|
||||
next.bTriggered = 1;
|
||||
if (AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (auto count = AuAtomicLoad(&this->uApproxSleepCount))
|
||||
{
|
||||
if (bits.bAtomicRelease)
|
||||
{
|
||||
LSSemaphore::AddOne();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (AU_ITERATE_N(n, count))
|
||||
{
|
||||
LSSemaphore::AddOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LSLocalEvent::OnPresleep()
|
||||
{
|
||||
AuAtomicAdd(&this->uApproxSleepCount, 1u);
|
||||
}
|
||||
|
||||
void LSLocalEvent::OnFinishSleep()
|
||||
{
|
||||
AuAtomicSub(&this->uApproxSleepCount, 1u);
|
||||
}
|
||||
|
||||
bool LSLocalEvent::Reset()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
EventBits bits, next;
|
||||
bits.state = AuAtomicLoad(&this->state_);
|
||||
|
||||
if (!bits.bTriggered)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
next.state = bits.state;
|
||||
next.bTriggered = 0;
|
||||
if (AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LSLocalEvent::TryTakeNoSpin()
|
||||
{
|
||||
EventBits bits;
|
||||
bits.state = AuAtomicLoad(&this->state_);
|
||||
if (bits.bAtomicRelease)
|
||||
{
|
||||
if (bits.bTriggered)
|
||||
{
|
||||
auto next = bits;
|
||||
next.bTriggered = 0;
|
||||
return AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return bits.bTriggered;
|
||||
}
|
||||
}
|
||||
|
||||
bool LSLocalEvent::TryTakeSpin()
|
||||
{
|
||||
return Threading::Primitives::DoTryIf([&]
|
||||
{
|
||||
return this->TryTakeNoSpin();
|
||||
});
|
||||
}
|
||||
|
||||
bool LSLocalEvent::TryTake()
|
||||
{
|
||||
return this->TryTakeNoSpin();
|
||||
}
|
||||
|
||||
bool LSLocalEvent::TryTakeWaitMS(AuUInt32 timeout)
|
||||
{
|
||||
auto uEndTime = AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(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;
|
||||
}
|
||||
|
||||
auto uDeltaMs = AuNSToMS<AuInt64>(uEndTime - uStartTime);
|
||||
if (uDeltaMs &&
|
||||
LSSemaphore::WaitOn(uDeltaMs))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AUKN_SYM AuSPtr<ILSEvent> NewLSEvent(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers)
|
||||
{
|
||||
auto pMutex = AuMakeShared<LSLocalEvent>();
|
||||
if (!pMutex)
|
||||
{
|
||||
SysPushErrorGeneric();
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!pMutex->TryInit(bTriggered, bAtomicRelease, bPermitMultipleTriggers))
|
||||
{
|
||||
SysPushErrorNested();
|
||||
return {};
|
||||
}
|
||||
|
||||
return pMutex;
|
||||
}
|
||||
}
|
63
Source/IO/Loop/LSLocalEvent.hpp
Normal file
63
Source/IO/Loop/LSLocalEvent.hpp
Normal file
@ -0,0 +1,63 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSLocalEvent.hpp
|
||||
Date: 2023-10-21
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
#include "LSSemaphore.hpp"
|
||||
|
||||
namespace Aurora::IO::Loop
|
||||
{
|
||||
struct LSLocalEvent : LSSemaphore, ILSEvent
|
||||
{
|
||||
LSLocalEvent();
|
||||
~LSLocalEvent();
|
||||
|
||||
bool TryInit(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers);
|
||||
|
||||
bool IsSignaled() override;
|
||||
bool WaitOn(AuUInt32 timeout) override;
|
||||
ELoopSource GetType() override;
|
||||
|
||||
bool Set() override;
|
||||
bool Reset() override;
|
||||
|
||||
virtual bool OnTrigger(AuUInt handle) override;
|
||||
|
||||
bool TryTakeNoSpin();
|
||||
bool TryTakeSpin();
|
||||
bool TryTake();
|
||||
bool TryTakeWaitMS(AuUInt32 timeout);
|
||||
|
||||
void OnPresleep() override;
|
||||
void OnFinishSleep() override;
|
||||
|
||||
union EventBits
|
||||
{
|
||||
struct
|
||||
{
|
||||
AuUInt8 bAtomicRelease : 1;
|
||||
AuUInt8 bPermitMultipleTriggers : 1;
|
||||
AuUInt8 bTriggered : 1;
|
||||
};
|
||||
AuUInt32 state;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
AuUInt8 bAtomicRelease_ : 1;
|
||||
AuUInt8 bPermitMultipleTriggers_ : 1;
|
||||
AuUInt8 bTriggered_ : 1;
|
||||
};
|
||||
|
||||
AuUInt32 state_;
|
||||
};
|
||||
|
||||
AuUInt32 uApproxSleepCount;
|
||||
};
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/***
|
||||
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: LSLocalMutex.hpp
|
||||
File: LSLocalSemaphore.hpp
|
||||
Date: 2023-10-21
|
||||
Author: Reece
|
||||
***/
|
||||
|
@ -183,7 +183,8 @@ namespace Aurora::IO::Loop
|
||||
|
||||
auto type = lsList[0];
|
||||
if (type->GetType() == ELoopSource::eSourceMutex ||
|
||||
type->GetType() == ELoopSource::eSourceSemaphore)
|
||||
type->GetType() == ELoopSource::eSourceSemaphore ||
|
||||
type->GetType() == ELoopSource::eSourceEvent)
|
||||
{
|
||||
for (AU_ITERATE_N(i, lsList.size()))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user