[+] IEvent::TrySet()
[+] New atomic logic for AuEvent. With this change, I can stop slandering it as the "shit primitive." (it's still not the best it could be, but it's an improvement over what i had before)
This commit is contained in:
parent
12a2f30f47
commit
48dc2e790b
@ -27,8 +27,9 @@ namespace Aurora::Threading::Primitives
|
|||||||
LockMS(ms);
|
LockMS(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
virtual void Set() = 0;
|
virtual void Set() = 0;
|
||||||
|
virtual bool TrySet() = 0; // returns false on bPermitMultipleTriggers volation
|
||||||
};
|
};
|
||||||
|
|
||||||
AUKN_SHARED_SOO2_NCM(Event, IEvent, kPrimitiveSizeEvent,
|
AUKN_SHARED_SOO2_NCM(Event, IEvent, kPrimitiveSizeEvent,
|
||||||
|
@ -34,6 +34,11 @@ namespace Aurora::Threading::Primitives
|
|||||||
AuInt64 uStartTime {};
|
AuInt64 uStartTime {};
|
||||||
AuInt64 uEndTime {};
|
AuInt64 uEndTime {};
|
||||||
|
|
||||||
|
if (AtomicIsEventSetLogicNoSpinNoLock())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (uTimeout)
|
if (uTimeout)
|
||||||
{
|
{
|
||||||
uStartTime = Time::SteadyClockNS();
|
uStartTime = Time::SteadyClockNS();
|
||||||
@ -42,7 +47,7 @@ namespace Aurora::Threading::Primitives
|
|||||||
|
|
||||||
AU_LOCK_GUARD(this->mutex_);
|
AU_LOCK_GUARD(this->mutex_);
|
||||||
|
|
||||||
while (!AtomicIsEventSetLogic())
|
while (!AtomicIsEventSetLogicNoSpinNoLock())
|
||||||
{
|
{
|
||||||
AuUInt32 uTimeoutNS {};
|
AuUInt32 uTimeoutNS {};
|
||||||
|
|
||||||
@ -68,41 +73,76 @@ namespace Aurora::Threading::Primitives
|
|||||||
|
|
||||||
bool EventImpl::TryLock()
|
bool EventImpl::TryLock()
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(this->mutex_);
|
return AtomicIsEventSetLogicNoSpinNoLock();
|
||||||
|
|
||||||
return AtomicIsEventSetLogic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventImpl::AtomicIsEventSetLogic()
|
bool EventImpl::AtomicIsEventSetLogicNoSpinNoLock()
|
||||||
{
|
{
|
||||||
if (!this->bTriggered_)
|
EventBits bits;
|
||||||
|
bits.state = AuAtomicLoad(&this->state_);
|
||||||
|
if (bits.bAtomicRelease)
|
||||||
{
|
{
|
||||||
return false;
|
if (bits.bTriggered)
|
||||||
|
{
|
||||||
|
auto next = bits;
|
||||||
|
next.bTriggered = 0;
|
||||||
|
return AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (this->bAtomicRelease_)
|
|
||||||
{
|
{
|
||||||
this->bTriggered_ = false;
|
return bits.bTriggered;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventImpl::Reset()
|
void EventImpl::Reset()
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(this->mutex_);
|
while (true)
|
||||||
this->bTriggered_ = false;
|
{
|
||||||
|
EventBits bits, next;
|
||||||
|
bits.state = AuAtomicLoad(&this->state_);
|
||||||
|
|
||||||
|
if (!bits.bTriggered)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
next.state = bits.state;
|
||||||
|
next.bTriggered = 0;
|
||||||
|
if (AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventImpl::Set()
|
void EventImpl::Set()
|
||||||
{
|
{
|
||||||
|
EventBits bits, next;
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
AU_LOCK_GUARD(this->mutex_);
|
bits.state = AuAtomicLoad(&this->state_);
|
||||||
SysAssertExp((this->bPermitMultipleTriggers_) || (!this->bTriggered_), "Can not trigger an awake event object");
|
|
||||||
this->bTriggered_ = true;
|
// TODO: runtime config option to turn this into a handable exception
|
||||||
|
SysAssertExp((bits.bPermitMultipleTriggers) || (!bits.bTriggered), "Can not trigger an awake event object");
|
||||||
|
|
||||||
|
next.state = bits.state;
|
||||||
|
next.bTriggered = 1;
|
||||||
|
if (AuAtomicCompareExchange(&this->state_, next.state, bits.state) == bits.state)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->bAtomicRelease_)
|
this->mutex_.Lock();
|
||||||
|
this->mutex_.Unlock();
|
||||||
|
|
||||||
|
if (bits.bAtomicRelease)
|
||||||
{
|
{
|
||||||
this->condition_.Signal();
|
this->condition_.Signal();
|
||||||
}
|
}
|
||||||
@ -112,6 +152,45 @@ namespace Aurora::Threading::Primitives
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EventImpl::TrySet()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mutex_.Lock();
|
||||||
|
this->mutex_.Unlock();
|
||||||
|
|
||||||
|
if (bits.bAtomicRelease)
|
||||||
|
{
|
||||||
|
this->condition_.Signal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->condition_.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool EventImpl::HasOSHandle(AuMach &mach)
|
bool EventImpl::HasOSHandle(AuMach &mach)
|
||||||
{
|
{
|
||||||
mach = 0;
|
mach = 0;
|
||||||
|
@ -23,13 +23,14 @@ namespace Aurora::Threading::Primitives
|
|||||||
bool TryLock() override;
|
bool TryLock() override;
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
void Set() override;
|
void Set() override;
|
||||||
|
bool TrySet() override;
|
||||||
bool HasOSHandle(AuMach &mach) override;
|
bool HasOSHandle(AuMach &mach) override;
|
||||||
bool HasLockImplementation() override;
|
bool HasLockImplementation() override;
|
||||||
void Lock() override;
|
void Lock() override;
|
||||||
void Unlock() override;
|
void Unlock() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool AtomicIsEventSetLogic();
|
bool AtomicIsEventSetLogicNoSpinNoLock();
|
||||||
|
|
||||||
ConditionMutexInternal mutex_; // must come first
|
ConditionMutexInternal mutex_; // must come first
|
||||||
ConditionVariableInternal condition_;
|
ConditionVariableInternal condition_;
|
||||||
@ -39,9 +40,30 @@ namespace Aurora::Threading::Primitives
|
|||||||
const bool bPermitMultipleTriggers_ {};
|
const bool bPermitMultipleTriggers_ {};
|
||||||
bool bTriggered_ {};
|
bool bTriggered_ {};
|
||||||
#else
|
#else
|
||||||
AuUInt8 bAtomicRelease_ : 1;
|
|
||||||
AuUInt8 bPermitMultipleTriggers_ : 1;
|
union EventBits
|
||||||
AuUInt8 bTriggered_ : 1;
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
AuUInt8 bAtomicRelease : 1;
|
||||||
|
AuUInt8 bPermitMultipleTriggers : 1;
|
||||||
|
AuUInt8 bTriggered : 1;
|
||||||
|
};
|
||||||
|
AuUInt8 state;
|
||||||
|
};
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
AuUInt8 bAtomicRelease_ : 1;
|
||||||
|
AuUInt8 bPermitMultipleTriggers_ : 1;
|
||||||
|
AuUInt8 bTriggered_ : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
AuUInt8 state_;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user