diff options
| author | Martin Ridgers <[email protected]> | 2021-11-11 14:17:18 +0100 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-11-11 14:17:18 +0100 |
| commit | d4d73addfeafbc1869d8a0252885483af2d9c7a8 (patch) | |
| tree | 595485bcd6f0b009600a265b8e93390d769d7b41 /zencore/thread.cpp | |
| parent | Removed unused u8string_view NamedEvent constructor (diff) | |
| download | zen-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.cpp | 83 |
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 +} ////////////////////////////////////////////////////////////////////////// |