aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/include
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2025-10-29 09:35:25 +0100
committerGitHub Enterprise <[email protected]>2025-10-29 09:35:25 +0100
commit2e293bbbf17639471d6d570212a09d097801da66 (patch)
tree1eb3d7e53952aee2ec8b3a2a43b839f3594de392 /src/zencore/include
parentfix --zentrace=no compile errors (#616) (diff)
downloadzen-2e293bbbf17639471d6d570212a09d097801da66.tar.xz
zen-2e293bbbf17639471d6d570212a09d097801da66.zip
fix for Latch race (#617)
Because the counter is decreased in `CountDown()` and subsequently checked against zero to determine if the completion event should be set: `Latch::Wait` checks the counter against zero on entry and would exit early, before waiting on the completion event. This could then lead to the `Latch` instance being torn down before the `CountDown()` does a `Set()` which could then lead to unexpected and unwanted things happening.
Diffstat (limited to 'src/zencore/include')
-rw-r--r--src/zencore/include/zencore/thread.h32
1 files changed, 11 insertions, 21 deletions
diff --git a/src/zencore/include/zencore/thread.h b/src/zencore/include/zencore/thread.h
index 11ef01a35..9fe6dfb9b 100644
--- a/src/zencore/include/zencore/thread.h
+++ b/src/zencore/include/zencore/thread.h
@@ -103,16 +103,12 @@ public:
ZENCORE_API Event();
ZENCORE_API ~Event();
- Event(Event&& Rhs) noexcept : m_EventHandle(Rhs.m_EventHandle) { Rhs.m_EventHandle = nullptr; }
+ Event(Event&& Rhs) noexcept : m_EventHandle(Rhs.m_EventHandle.load()) { Rhs.m_EventHandle = nullptr; }
Event(const Event& Rhs) = delete;
Event& operator=(const Event& Rhs) = delete;
- inline Event& operator=(Event&& Rhs) noexcept
- {
- std::swap(m_EventHandle, Rhs.m_EventHandle);
- return *this;
- }
+ Event& operator=(Event&& Rhs) = delete;
ZENCORE_API void Set();
ZENCORE_API void Reset();
@@ -126,7 +122,7 @@ public:
protected:
explicit Event(void* EventHandle) : m_EventHandle(EventHandle) {}
- void* m_EventHandle = nullptr;
+ std::atomic<void*> m_EventHandle{nullptr};
};
/** Basic abstraction of an IPC mechanism (aka 'binary semaphore')
@@ -141,16 +137,18 @@ public:
ZENCORE_API std::error_code Set();
ZENCORE_API bool Wait(int TimeoutMs = -1);
- NamedEvent(NamedEvent&& Rhs) noexcept : m_EventHandle(Rhs.m_EventHandle) { Rhs.m_EventHandle = nullptr; }
+ NamedEvent(NamedEvent&& Rhs) noexcept : m_EventHandle(Rhs.m_EventHandle.load()) { Rhs.m_EventHandle = nullptr; }
- inline NamedEvent& operator=(NamedEvent&& Rhs) noexcept
+ NamedEvent& operator=(NamedEvent&& Rhs)
{
- std::swap(m_EventHandle, Rhs.m_EventHandle);
+ Close();
+ m_EventHandle = Rhs.m_EventHandle.load();
+ Rhs.m_EventHandle = nullptr;
return *this;
- }
+ };
protected:
- void* m_EventHandle = nullptr;
+ std::atomic<void*> m_EventHandle{nullptr};
private:
NamedEvent(const NamedEvent& Rhs) = delete;
@@ -201,15 +199,7 @@ public:
ZEN_ASSERT(Old > 0);
}
- bool Wait(int TimeoutMs = -1)
- {
- std::ptrdiff_t Old = Counter.load();
- if (Old == 0)
- {
- return true;
- }
- return Complete.Wait(TimeoutMs);
- }
+ bool Wait(int TimeoutMs = -1) { return Complete.Wait(TimeoutMs); }
private:
std::atomic_ptrdiff_t Counter;