aboutsummaryrefslogtreecommitdiff
path: root/zencore/thread.cpp
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2022-01-13 09:54:29 +0100
committerMartin Ridgers <[email protected]>2022-01-13 09:54:29 +0100
commitf60ea144e4df366ca9210a7c90973b11be2402c8 (patch)
tree097c6f3ff16d32243c9d3c634e2d909069d5f1f3 /zencore/thread.cpp
parentIssue warning if xmake bundle is run on non-Windows (diff)
downloadzen-f60ea144e4df366ca9210a7c90973b11be2402c8.tar.xz
zen-f60ea144e4df366ca9210a7c90973b11be2402c8.zip
Use SysV semaphores to implement NamedEvent on Linux
Diffstat (limited to 'zencore/thread.cpp')
-rw-r--r--zencore/thread.cpp107
1 files changed, 7 insertions, 100 deletions
diff --git a/zencore/thread.cpp b/zencore/thread.cpp
index 97d44e733..de8b5f515 100644
--- a/zencore/thread.cpp
+++ b/zencore/thread.cpp
@@ -27,19 +27,12 @@
# include <pthread.h>
# include <signal.h>
# include <sys/file.h>
+# include <sys/sem.h>
# include <sys/wait.h>
# include <time.h>
# include <unistd.h>
#endif
-#if ZEN_PLATFORM_LINUX
-# include <mqueue.h>
-#endif
-
-#if ZEN_PLATFORM_MAC
-# include <sys/sem.h>
-#endif
-
#include <thread>
ZEN_THIRD_PARTY_INCLUDES_START
@@ -249,17 +242,6 @@ Event::Wait(int TimeoutMs)
//////////////////////////////////////////////////////////////////////////
-#if ZEN_PLATFORM_LINUX
-static bool
-IsMessageQueueEmpty(int Fd)
-{
- // Check if there is already a message in the queue.
- mq_attr Attributes = {O_NONBLOCK, 1, 1, 0};
- mq_getattr(Fd, &Attributes);
- return (Attributes.mq_curmsgs == 0);
-}
-#endif // ZEN_PLATFORM_LINUX
-
NamedEvent::NamedEvent(std::string_view EventName)
{
#if ZEN_PLATFORM_WINDOWS
@@ -270,39 +252,7 @@ NamedEvent::NamedEvent(std::string_view EventName)
Name << EventName;
m_EventHandle = CreateEventA(nullptr, true, false, Name.c_str());
-#elif ZEN_PLATFORM_LINUX
- ExtendableStringBuilder<64> Name;
- Name << "/";
- Name << EventName;
-
- mq_attr Attributes = {
- 0, // flags
- 1, // max message count
- 1, // max message size
- 0, // current messages
- };
-
- int Inner = mq_open(Name.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0644, &Attributes);
- if (Inner < 0)
- {
- ThrowLastError("Failed to get message queue from mq_open()");
- }
-
- int LockResult = flock(Inner, LOCK_EX | LOCK_NB);
- if (LockResult == 0)
- {
- // This isn't really thread safe as the message queue could be set
- // between getting the exclusive lock and checking the queue. But for
- // the our simple synchronising of process, this should be okay.
- while (!IsMessageQueueEmpty(Inner))
- {
- char Sink;
- mq_receive(Inner, &Sink, sizeof(Sink), nullptr);
- }
- }
-
- m_EventHandle = (void*)intptr_t(Inner);
-#elif ZEN_PLATFORM_MAC
+#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
// Create a file to back the semaphore
ExtendableStringBuilder<64> EventPath;
EventPath << "/tmp/" << EventName;
@@ -365,18 +315,7 @@ NamedEvent::Close()
#if ZEN_PLATFORM_WINDOWS
CloseHandle(m_EventHandle);
-#elif ZEN_PLATFORM_LINUX
- int Inner = int(intptr_t(m_EventHandle));
-
- if (flock(Inner, LOCK_EX | LOCK_NB) == 0)
- {
- flock(Inner, LOCK_UN | LOCK_NB);
- std::filesystem::path Name = PathFromHandle((void*)(intptr_t(Inner)));
- mq_unlink(Name.c_str());
- }
-
- close(Inner);
-#elif ZEN_PLATFORM_MAC
+#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
int Fd = int(intptr_t(m_EventHandle) & 0xffff'ffff);
if (flock(Fd, LOCK_EX | LOCK_NB) == 0)
@@ -400,20 +339,7 @@ NamedEvent::Set()
{
#if ZEN_PLATFORM_WINDOWS
SetEvent(m_EventHandle);
-#elif ZEN_PLATFORM_LINUX
- int Inner = int(intptr_t(m_EventHandle));
-
- if (!IsMessageQueueEmpty(Inner))
- {
- return;
- }
-
- char Message = 0x49;
- if (mq_send(Inner, &Message, sizeof(Message), 0) != 0)
- {
- ThrowLastError("Unable to send set message to queue");
- }
-#elif ZEN_PLATFORM_MAC
+#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
int Sem = int(intptr_t(m_EventHandle) >> 32);
semctl(Sem, 0, SETVAL, 0);
#endif
@@ -434,25 +360,7 @@ NamedEvent::Wait(int TimeoutMs)
}
return (Result == WAIT_OBJECT_0);
-#elif ZEN_PLATFORM_LINUX
- int Inner = int(intptr_t(m_EventHandle));
-
- if (!IsMessageQueueEmpty(Inner))
- {
- return true;
- }
-
- struct timeval TimeoutValue = {
- .tv_sec = (TimeoutMs >> 10),
- .tv_usec = (TimeoutMs & 0x3ff) << 10,
- };
- struct timeval* TimeoutPtr = (TimeoutMs < 0) ? nullptr : &TimeoutValue;
-
- fd_set FdSet;
- FD_ZERO(&FdSet);
- FD_SET(Inner, &FdSet);
- return select(Inner + 1, &FdSet, nullptr, nullptr, TimeoutPtr) > 0;
-#elif ZEN_PLATFORM_MAC
+#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
int Sem = int(intptr_t(m_EventHandle) >> 32);
int Result;
@@ -469,8 +377,7 @@ NamedEvent::Wait(int TimeoutMs)
.tv_sec = TimeoutMs >> 10,
.tv_nsec = (TimeoutMs & 0x3ff) << 20,
};
- int Result = semtimedop(Sem, &SemOp, 1, &TimeoutValue);
- return Result == 0;
+ Result = semtimedop(Sem, &SemOp, 1, &TimeoutValue);
#else
const int SleepTimeMs = 10;
SemOp.sem_flg = IPC_NOWAIT;
@@ -486,9 +393,9 @@ NamedEvent::Wait(int TimeoutMs)
TimeoutMs -= SleepTimeMs;
}
while (TimeoutMs > 0);
+#endif // _GNU_SOURCE
return Result == 0;
-#endif // _GNU_SOURCE
#endif
}