From d4d73addfeafbc1869d8a0252885483af2d9c7a8 Mon Sep 17 00:00:00 2001 From: Martin Ridgers Date: Thu, 11 Nov 2021 14:17:18 +0100 Subject: Implement NamedEvent on POSIX using Unix-domain sockets --- zencore/thread.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) (limited to 'zencore/thread.cpp') 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 # include +# include # include # include +# include +# include # include # include #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 +} ////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3