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 <climits>
7
8 #include "gaia/mt/win32.h"
9#elif GAIA_PLATFORM_APPLE
10 #include <TargetConditionals.h>
11 #include <dispatch/dispatch.h>
12 #include <pthread.h>
13#else
14 #include <pthread.h>
15 #include <semaphore.h>
16#endif
17
18namespace gaia {
19 namespace mt {
21 class GAIA_API Semaphore final {
22#if GAIA_PLATFORM_WINDOWS
23 void* m_handle;
24#elif GAIA_PLATFORM_APPLE
25 dispatch_semaphore_t m_handle;
26#else
27 sem_t m_handle;
28#endif
29
30 Semaphore(Semaphore&&) = delete;
31 Semaphore(const Semaphore&) = delete;
32 Semaphore& operator=(Semaphore&&) = delete;
33 Semaphore& operator=(const Semaphore&) = delete;
34
37 void init(int32_t count) {
38#if GAIA_PLATFORM_WINDOWS
39 m_handle = ::CreateSemaphoreExW(nullptr, count, INT_MAX, nullptr, 0, win32::SemaphoreAllAccess);
40 GAIA_ASSERT(m_handle != nullptr);
41#elif GAIA_PLATFORM_APPLE
42 m_handle = dispatch_semaphore_create(count);
43 GAIA_ASSERT(m_handle != nullptr);
44#else
45 [[maybe_unused]] int ret = sem_init(&m_handle, 0, (unsigned int)count);
46 GAIA_ASSERT(ret == 0);
47#endif
48 }
49
51 void done() {
52#if GAIA_PLATFORM_WINDOWS
53 if (m_handle != nullptr) {
54 ::CloseHandle(m_handle);
55 m_handle = nullptr;
56 }
57#elif GAIA_PLATFORM_APPLE
58 // NOTE: Dispatch objects are reference counted.
59 // They are automatically released when no longer used.
60 // -> dispatch_release(m_handle);
61#else
62 [[maybe_unused]] int ret = sem_destroy(&m_handle);
63 GAIA_ASSERT(ret == 0);
64#endif
65 }
66
67 public:
70 explicit Semaphore(int32_t count = 0) {
71 init(count);
72 }
73
74 ~Semaphore() {
75 done();
76 }
77
80 void release(int32_t count) {
81 GAIA_ASSERT(count > 0);
82
83#if GAIA_PLATFORM_WINDOWS
84 [[maybe_unused]] long prev = 0;
85 [[maybe_unused]] int res = ::ReleaseSemaphore(m_handle, count, &prev);
86 GAIA_ASSERT(res != 0);
87#elif GAIA_PLATFORM_APPLE
88 do {
89 dispatch_semaphore_signal(m_handle);
90 } while ((--count) != 0);
91#else
92 do {
93 [[maybe_unused]] const auto ret = sem_post(&m_handle);
94 GAIA_ASSERT(ret == 0);
95 } while ((--count) != 0);
96#endif
97 }
98
103 bool wait() {
104#if GAIA_PLATFORM_WINDOWS
105 GAIA_ASSERT(m_handle != nullptr);
106 const unsigned long ret = ::WaitForSingleObject(m_handle, win32::Infinite);
107 GAIA_ASSERT(ret == win32::WaitObject0);
108 return (ret == win32::WaitObject0);
109#elif GAIA_PLATFORM_APPLE
110 const auto res = dispatch_semaphore_wait(m_handle, DISPATCH_TIME_FOREVER);
111 GAIA_ASSERT(res == 0);
112 return (res == 0);
113#else
114 int res;
115 do {
116 res = sem_wait(&m_handle);
117 } while (res == -1 && errno == EINTR); // handle interrupts
118
119 GAIA_ASSERT(res == 0);
120 return (res == 0);
121#endif
122 }
123 };
124 } // namespace mt
125} // namespace gaia
Portable counting semaphore with indefinite waits.
Definition semaphore.h:21
Semaphore(int32_t count=0)
Creates a semaphore with an initial count.
Definition semaphore.h:70
void release(int32_t count)
Increments semaphore count by the specified amount.
Definition semaphore.h:80
bool wait()
Decrements semaphore count by 1. If the count is already 0, it waits indefinitely until semaphore cou...
Definition semaphore.h:103