aboutsummaryrefslogtreecommitdiff
path: root/zencore/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zencore/thread.cpp')
-rw-r--r--zencore/thread.cpp110
1 files changed, 103 insertions, 7 deletions
diff --git a/zencore/thread.cpp b/zencore/thread.cpp
index da711fe89..ff86ff5fc 100644
--- a/zencore/thread.cpp
+++ b/zencore/thread.cpp
@@ -4,10 +4,16 @@
#include <zencore/except.h>
#include <zencore/string.h>
+#include <zencore/testing.h>
#if ZEN_PLATFORM_WINDOWS
# include <zencore/windows.h>
#elif ZEN_PLATFORM_LINUX
+# include <chrono>
+# include <condition_variable>
+# include <mutex>
+
+# include <pthread.h>
# include <unistd.h>
#endif
@@ -69,6 +75,8 @@ SetCurrentThreadName([[maybe_unused]] std::string_view ThreadName)
std::string ThreadNameZ{ThreadName};
SetNameInternal(GetCurrentThreadId(), ThreadNameZ.c_str());
#else
+ std::string ThreadNameZ{ThreadName};
+ pthread_setname_np(pthread_self(), ThreadNameZ.c_str());
#endif
} // namespace zen
@@ -98,40 +106,80 @@ RwLock::ReleaseExclusive()
//////////////////////////////////////////////////////////////////////////
-#if ZEN_PLATFORM_WINDOWS
+#if !ZEN_PLATFORM_WINDOWS
+struct EventInner
+{
+ std::mutex Mutex;
+ std::condition_variable CondVar;
+ bool volatile bSet = false;
+};
+#endif // !ZEN_PLATFORM_WINDOWS
Event::Event()
{
- m_EventHandle = CreateEvent(nullptr, true, false, nullptr);
+ bool bManualReset = true;
+ bool bInitialState = false;
+
+#if ZEN_PLATFORM_WINDOWS
+ m_EventHandle = CreateEvent(nullptr, bManualReset, bInitialState, nullptr);
+#else
+ ZEN_UNUSED(bManualReset);
+ auto* Inner = new EventInner();
+ Inner->bSet = bInitialState;
+ m_EventHandle = Inner;
+#endif
}
Event::~Event()
{
- CloseHandle(m_EventHandle);
+ Close();
}
void
Event::Set()
{
+#if ZEN_PLATFORM_WINDOWS
SetEvent(m_EventHandle);
+#else
+ auto* Inner = (EventInner*)m_EventHandle;
+ {
+ std::unique_lock Lock(Inner->Mutex);
+ Inner->bSet = true;
+ }
+ Inner->CondVar.notify_all();
+#endif
}
void
Event::Reset()
{
+#if ZEN_PLATFORM_WINDOWS
ResetEvent(m_EventHandle);
+#else
+ auto* Inner = (EventInner*)m_EventHandle;
+ {
+ std::unique_lock Lock(Inner->Mutex);
+ Inner->bSet = false;
+ }
+#endif
}
void
Event::Close()
{
+#if ZEN_PLATFORM_WINDOWS
CloseHandle(m_EventHandle);
+#else
+ auto* Inner = (EventInner*)m_EventHandle;
+ delete Inner;
+#endif
m_EventHandle = nullptr;
}
bool
Event::Wait(int TimeoutMs)
{
+#if ZEN_PLATFORM_WINDOWS
using namespace std::literals;
const DWORD Timeout = (TimeoutMs < 0) ? INFINITE : TimeoutMs;
@@ -144,10 +192,29 @@ Event::Wait(int TimeoutMs)
}
return (Result == WAIT_OBJECT_0);
+#else
+ auto* Inner = (EventInner*)m_EventHandle;
+
+ if (TimeoutMs >= 0)
+ {
+ std::unique_lock Lock(Inner->Mutex);
+ return Inner->CondVar.wait_for(
+ Lock,
+ std::chrono::milliseconds(TimeoutMs),
+ [&] { return Inner->bSet; }
+ );
+ }
+
+ std::unique_lock Lock(Inner->Mutex);
+ Inner->CondVar.wait(Lock, [&] { return Inner->bSet; });
+ return true;
+#endif
}
//////////////////////////////////////////////////////////////////////////
+#if ZEN_PLATFORM_WINDOWS
+
NamedEvent::NamedEvent(std::u8string_view EventName) : Event(nullptr)
{
using namespace std::literals;
@@ -170,6 +237,12 @@ NamedEvent::NamedEvent(std::string_view EventName) : Event(nullptr)
m_EventHandle = CreateEventA(nullptr, true, false, Name.c_str());
}
+#endif // ZEN_PLATFORM_WINDOWS
+
+//////////////////////////////////////////////////////////////////////////
+
+#if ZEN_PLATFORM_WINDOWS
+
NamedMutex::~NamedMutex()
{
if (m_MutexHandle)
@@ -217,10 +290,10 @@ NamedMutex::Exists(std::string_view MutexName)
#endif // ZEN_PLATFORM_WINDOWS
-#if ZEN_PLATFORM_WINDOWS
-
//////////////////////////////////////////////////////////////////////////
+#if ZEN_PLATFORM_WINDOWS
+
ProcessHandle::ProcessHandle() = default;
void
@@ -418,7 +491,9 @@ IsProcessRunning(int pid)
return true;
#else
- ZEN_NOT_IMPLEMENTED();
+ char Buffer[64];
+ sprintf(Buffer, "/proc/%d", pid);
+ return access(Buffer, F_OK) == 0;
#endif
}
@@ -428,7 +503,17 @@ GetCurrentProcessId()
#if ZEN_PLATFORM_WINDOWS
return ::GetCurrentProcessId();
#else
- return getpid();
+ return int(getpid());
+#endif
+}
+
+int
+GetCurrentThreadId()
+{
+#if ZEN_PLATFORM_WINDOWS
+ return ::GetCurrentThreadId();
+#else
+ return int(gettid());
#endif
}
@@ -447,9 +532,20 @@ Sleep(int ms)
// Testing related code follows...
//
+#if ZEN_WITH_TESTS
+
void
thread_forcelink()
{
}
+TEST_CASE("Thread")
+{
+ int Pid = GetCurrentProcessId();
+ CHECK(Pid > 0);
+ CHECK(IsProcessRunning(Pid));
+}
+
+#endif // ZEN_WITH_TESTS
+
} // namespace zen