Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
semaphore.h
1#pragma once
2
3#include "gaia/config/config.h"
4
5#if GAIA_PLATFORM_WINDOWS
6 #include <windows.h>
7#elif GAIA_PLATFORM_APPLE
8 #include <TargetConditionals.h>
9 #include <dispatch/dispatch.h>
10 #include <pthread.h>
11#else
12 #include <pthread.h>
13 #include <semaphore.h>
14#endif
15
16namespace gaia {
17 namespace mt {
19 class GAIA_API Semaphore final {
20#if GAIA_PLATFORM_WINDOWS
21 void* m_handle;
22#elif GAIA_PLATFORM_APPLE
23 dispatch_semaphore_t m_handle;
24#else
25 sem_t m_handle;
26#endif
27
28 Semaphore(Semaphore&&) = delete;
29 Semaphore(const Semaphore&) = delete;
30 Semaphore& operator=(Semaphore&&) = delete;
31 Semaphore& operator=(const Semaphore&) = delete;
32
35 void init(int32_t count) {
36#if GAIA_PLATFORM_WINDOWS
37 m_handle = (void*)::CreateSemaphoreExW(NULL, count, INT_MAX, NULL, 0, SEMAPHORE_ALL_ACCESS);
38 GAIA_ASSERT(m_handle != NULL);
39#elif GAIA_PLATFORM_APPLE
40 m_handle = dispatch_semaphore_create(count);
41 GAIA_ASSERT(m_handle != nullptr);
42#else
43 [[maybe_unused]] int ret = sem_init(&m_handle, 0, count);
44 GAIA_ASSERT(ret == 0);
45#endif
46 }
47
49 void done() {
50#if GAIA_PLATFORM_WINDOWS
51 if (m_handle != NULL) {
52 ::CloseHandle((HANDLE)m_handle);
53 m_handle = NULL;
54 }
55#elif GAIA_PLATFORM_APPLE
56 // NOTE: Dispatch objects are reference counted.
57 // They are automatically released when no longer used.
58 // -> dispatch_release(m_handle);
59#else
60 [[maybe_unused]] int ret = sem_destroy(&m_handle);
61 GAIA_ASSERT(ret == 0);
62#endif
63 }
64
65 public:
68 explicit Semaphore(int32_t count = 0) {
69 init(count);
70 }
71
72 ~Semaphore() {
73 done();
74 }
75
78 void release(int32_t count) {
79 GAIA_ASSERT(count > 0);
80
81#if GAIA_PLATFORM_WINDOWS
82 [[maybe_unused]] LONG prev = 0;
83 [[maybe_unused]] BOOL res = ::ReleaseSemaphore(m_handle, count, &prev);
84 GAIA_ASSERT(res != 0);
85#elif GAIA_PLATFORM_APPLE
86 do {
87 dispatch_semaphore_signal(m_handle);
88 } while ((--count) != 0);
89#else
90 do {
91 [[maybe_unused]] const auto ret = sem_post(&m_handle);
92 GAIA_ASSERT(ret == 0);
93 } while ((--count) != 0);
94#endif
95 }
96
101 bool wait() {
102#if GAIA_PLATFORM_WINDOWS
103 GAIA_ASSERT(m_handle != (void*)ERROR_INVALID_HANDLE);
104 DWORD ret = ::WaitForSingleObject(m_handle, INFINITE);
105 GAIA_ASSERT(ret == WAIT_OBJECT_0);
106 return (ret == WAIT_OBJECT_0);
107#elif GAIA_PLATFORM_APPLE
108 const auto res = dispatch_semaphore_wait(m_handle, DISPATCH_TIME_FOREVER);
109 GAIA_ASSERT(res == 0);
110 return (res == 0);
111#else
112 int res;
113 do {
114 res = sem_wait(&m_handle);
115 } while (res == -1 && errno == EINTR); // handle interrupts
116
117 GAIA_ASSERT(res == 0);
118 return (res == 0);
119#endif
120 }
121 };
122 } // namespace mt
123} // namespace gaia
Portable counting semaphore with indefinite waits.
Definition semaphore.h:19
Semaphore(int32_t count=0)
Creates a semaphore with an initial count.
Definition semaphore.h:68
void release(int32_t count)
Increments semaphore count by the specified amount.
Definition semaphore.h:78
bool wait()
Decrements semaphore count by 1. If the count is already 0, it waits indefinitely until semaphore cou...
Definition semaphore.h:101