aboutsummaryrefslogtreecommitdiff
path: root/zencore/thread.cpp
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2021-11-11 14:17:18 +0100
committerMartin Ridgers <[email protected]>2021-11-11 14:17:18 +0100
commitd4d73addfeafbc1869d8a0252885483af2d9c7a8 (patch)
tree595485bcd6f0b009600a265b8e93390d769d7b41 /zencore/thread.cpp
parentRemoved unused u8string_view NamedEvent constructor (diff)
downloadzen-d4d73addfeafbc1869d8a0252885483af2d9c7a8.tar.xz
zen-d4d73addfeafbc1869d8a0252885483af2d9c7a8.zip
Implement NamedEvent on POSIX using Unix-domain sockets
Diffstat (limited to 'zencore/thread.cpp')
-rw-r--r--zencore/thread.cpp83
1 files changed, 80 insertions, 3 deletions
diff --git a/zencore/thread.cpp b/zencore/thread.cpp
index df8b0301f..0b9534c39 100644
--- a/zencore/thread.cpp
+++ b/zencore/thread.cpp
@@ -13,8 +13,11 @@
# include <condition_variable>
# include <mutex>
+# include <poll.h>
# include <pthread.h>
# include <signal.h>
+# include <sys/socket.h>
+# include <sys/un.h>
# include <time.h>
# include <unistd.h>
#endif
@@ -226,10 +229,18 @@ Event::Wait(int TimeoutMs)
//////////////////////////////////////////////////////////////////////////
-#if ZEN_PLATFORM_WINDOWS
+#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MACOS
+struct NamedEventPosix
+{
+ int SocketFd = 0;
+ sockaddr_un SocketAddr = {};
+ bool bBound = false;
+};
+#endif
NamedEvent::NamedEvent(std::string_view EventName)
{
+#if ZEN_PLATFORM_WINDOWS
using namespace std::literals;
ExtendableStringBuilder<64> Name;
@@ -237,6 +248,27 @@ NamedEvent::NamedEvent(std::string_view EventName)
Name << EventName;
m_EventHandle = CreateEventA(nullptr, true, false, Name.c_str());
+#else
+ int SocketFd = socket(AF_UNIX, SOCK_DGRAM, SOCK_CLOEXEC);
+ if (SocketFd < 0)
+ {
+ ThrowLastError("Failed to create IPC socket");
+ }
+
+ auto* Inner = new NamedEventPosix();
+ Inner->SocketFd = SocketFd;
+
+ char* PathPtr = Inner->SocketAddr.sun_path;
+ size_t PathLen = sizeof(Inner->SocketAddr.sun_path) - 1; // -1 for null-term
+# if ZEN_PLATFORM_LINUX
+ PathPtr[0] = '\0'; // make the domain socket...
+ PathPtr += 1; // ...use the abstract namespace
+ PathLen -= 1;
+# endif
+ EventName.copy(PathPtr, PathLen);
+#endif
+
+ m_EventHandle = Inner;
}
NamedEvent::~NamedEvent()
@@ -251,18 +283,37 @@ void NamedEvent::Close()
return;
}
+#if ZEN_PLATFORM_WINDOWS
CloseHandle(m_EventHandle);
+#else
+ auto* Inner = (NamedEventPosix*)m_EventHandle;
+ close(Inner->SocketFd);
+ delete Inner;
+#endif
m_EventHandle = nullptr;
}
+
void NamedEvent::Set()
{
+#if ZEN_PLATFORM_WINDOWS
SetEvent(m_EventHandle);
+#else
+ auto* Inner = (NamedEventPosix*)m_EventHandle;
+
+ uint8_t OneByte = 0x49;
+ sendto(
+ Inner->SocketFd,
+ &OneByte, sizeof(OneByte),
+ 0, (sockaddr*)&Inner->SocketAddr, sizeof(Inner->SocketAddr)
+ );
+#endif
}
bool NamedEvent::Wait(int TimeoutMs)
{
+#if ZEN_PLATFORM_WINDOWS
const DWORD Timeout = (TimeoutMs < 0) ? INFINITE : TimeoutMs;
DWORD Result = WaitForSingleObject(m_EventHandle, Timeout);
@@ -274,9 +325,35 @@ bool NamedEvent::Wait(int TimeoutMs)
}
return (Result == WAIT_OBJECT_0);
-}
+#else
+ auto* Inner = (NamedEventPosix*)m_EventHandle;
+ int SocketFd = Inner->SocketFd;
-#endif // ZEN_PLATFORM_WINDOWS
+ int Result;
+
+ if (!Inner->bBound)
+ {
+ Result = bind(SocketFd, (sockaddr*)&(Inner->SocketAddr), sizeof(Inner->SocketAddr));
+ if (!Result)
+ {
+ zen::ThrowLastError("Bind IPC socket failed");
+ }
+ Inner->bBound = true;
+ }
+
+ pollfd PollFd = { SocketFd, POLLIN };
+ Result = poll(&PollFd, 1, TimeoutMs);
+ if (Result > 0)
+ {
+ uint8_t OneByte;
+ Result = recv(SocketFd, &OneByte, sizeof(OneByte), 0);
+
+ return true;
+ }
+
+ return false;
+#endif
+}
//////////////////////////////////////////////////////////////////////////