From 85097e245029ec973182e07ef79b966e748d0efa Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Thu, 16 Nov 2023 17:24:36 +0100 Subject: further posix event improvements (#549) * changed posix event implementation to use std::atomic instead of volatile * ensure Event::Close() can take lock before deleting the inner object * don't try to take the Event lock if the event is already signaled * changed logic around Event::Wait without time-out. this works around some apparent issues on MacOS/Linux * fix logic for posix process exit wait --- src/zencore/thread.cpp | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'src/zencore/thread.cpp') diff --git a/src/zencore/thread.cpp b/src/zencore/thread.cpp index 27a5ec1ae..1174f902f 100644 --- a/src/zencore/thread.cpp +++ b/src/zencore/thread.cpp @@ -190,7 +190,7 @@ Event::Set() auto* Inner = (EventInner*)m_EventHandle; { std::unique_lock Lock(Inner->Mutex); - Inner->bSet = true; + Inner->bSet.store(true); } Inner->CondVar.notify_all(); #endif @@ -205,7 +205,7 @@ Event::Reset() auto* Inner = (EventInner*)m_EventHandle; { std::unique_lock Lock(Inner->Mutex); - Inner->bSet = false; + Inner->bSet.store(false); } #endif } @@ -217,6 +217,10 @@ Event::Close() CloseHandle(m_EventHandle); #else auto* Inner = (EventInner*)m_EventHandle; + { + std::unique_lock Lock(Inner->Mutex); + Inner->bSet.store(true); + } delete Inner; #endif m_EventHandle = nullptr; @@ -239,13 +243,18 @@ Event::Wait(int TimeoutMs) return (Result == WAIT_OBJECT_0); #else - auto* Inner = (EventInner*)m_EventHandle; + auto* Inner = reinterpret_cast(m_EventHandle); + + if (Inner->bSet.load()) + { + return true; + } if (TimeoutMs >= 0) { std::unique_lock Lock(Inner->Mutex); - if (Inner->bSet) + if (Inner->bSet.load()) { return true; } @@ -253,11 +262,15 @@ Event::Wait(int TimeoutMs) return Inner->CondVar.wait_for(Lock, std::chrono::milliseconds(TimeoutMs), [&] { return Inner->bSet.load(); }); } + // Infinite wait. This does not actually call the wait() function to work around + // an apparent issue in the underlying implementation. + std::unique_lock Lock(Inner->Mutex); - if (!Inner->bSet) + if (!Inner->bSet.load()) { - Inner->CondVar.wait(Lock, [&] { return Inner->bSet.load(); }); + while (!Inner->CondVar.wait_for(Lock, std::chrono::milliseconds(1000), [&] { return Inner->bSet.load(); })) + ; } return true; @@ -656,6 +669,9 @@ ProcessHandle::Wait(int TimeoutMs) { int WaitState = 0; int Res = waitpid(m_Pid, &WaitState, WNOHANG | WCONTINUED | WUNTRACED); +# if 1 + ZEN_UNUSED(Res); +# else if (Res == -1) { int32_t LastError = zen::GetLastError(); @@ -665,6 +681,7 @@ ProcessHandle::Wait(int TimeoutMs) } ThrowSystemError(static_cast(LastError), "Process::Wait waitpid failed"sv); } +# endif if (kill(m_Pid, 0) < 0) { -- cgit v1.2.3