18#include <dispatch/dispatch.h>
19#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
22#elif defined(_WIN32) || defined(_WIN64)
35 explicit Impl(
int resources) : _resources(resources)
37 assert((resources > 0) &&
"Semaphore resources counter must be greater than zero!");
40 _semaphore = dispatch_semaphore_create(resources);
41 if (_semaphore ==
nullptr)
42 throwex SystemException(
"Failed to initialize a semaphore!");
43#elif defined(unix) || defined(__unix) || defined(__unix__)
44 int result = sem_init(&_semaphore, 0, resources);
46 throwex SystemException(
"Failed to initialize a semaphore!");
47#elif defined(_WIN32) || defined(_WIN64)
48 _semaphore = CreateSemaphore(
nullptr, resources, resources,
nullptr);
49 if (_semaphore ==
nullptr)
50 throwex SystemException(
"Failed to create a semaphore!");
57 if (_semaphore !=
nullptr)
58 dispatch_release(_semaphore);
59#elif defined(unix) || defined(__unix) || defined(__unix__)
60 int result = sem_destroy(&_semaphore);
62 fatality(SystemException(
"Failed to destroy a semaphore!"));
63#elif defined(_WIN32) || defined(_WIN64)
64 if (!CloseHandle(_semaphore))
65 fatality(SystemException(
"Failed to close a semaphore!"));
69 int resources() const noexcept
77 return (dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_NOW) == 0);
78#elif defined(unix) || defined(__unix) || defined(__unix__)
79 int result = sem_trywait(&_semaphore);
80 if ((result != 0) && (errno != EAGAIN))
81 throwex SystemException(
"Failed to try lock a semaphore!");
83#elif defined(_WIN32) || defined(_WIN64)
84 DWORD result = WaitForSingleObject(_semaphore, 0);
85 if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
86 throwex SystemException(
"Failed to try lock a semaphore!");
87 return (result == WAIT_OBJECT_0);
91 bool TryLockFor(
const Timespan& timespan)
96 dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, timespan.nanoseconds());
97 return (dispatch_semaphore_wait(_semaphore, timeout) == 0);
98#elif defined(unix) || defined(__unix) || defined(__unix__)
99 struct timespec timeout;
100 timeout.tv_sec = timespan.seconds();
101 timeout.tv_nsec = timespan.nanoseconds() % 1000000000;
102 int result = sem_timedwait(&_semaphore, &timeout);
103 if ((result != 0) && (errno != ETIMEDOUT))
104 throwex SystemException(
"Failed to try lock a semaphore for the given timeout!");
105 return (result == 0);
106#elif defined(_WIN32) || defined(_WIN64)
107 DWORD result = WaitForSingleObject(_semaphore, std::max((DWORD)1, (DWORD)timespan.milliseconds()));
108 if ((result != WAIT_OBJECT_0) && (result != WAIT_TIMEOUT))
109 throwex SystemException(
"Failed to try lock a semaphore for the given timeout!");
110 return (result == WAIT_OBJECT_0);
116#if defined(__APPLE__)
117 dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
118#elif defined(unix) || defined(__unix) || defined(__unix__)
119 int result = sem_wait(&_semaphore);
121 throwex SystemException(
"Failed to lock a semaphore!");
122#elif defined(_WIN32) || defined(_WIN64)
123 DWORD result = WaitForSingleObject(_semaphore, INFINITE);
124 if (result != WAIT_OBJECT_0)
125 throwex SystemException(
"Failed to lock a semaphore!");
131#if defined(__APPLE__)
132 dispatch_semaphore_signal(_semaphore);
133#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
134 int result = sem_post(&_semaphore);
136 throwex SystemException(
"Failed to unlock a semaphore!");
137#elif defined(_WIN32) || defined(_WIN64)
138 if (!ReleaseSemaphore(_semaphore, 1,
nullptr))
139 throwex SystemException(
"Failed to unlock a semaphore!");
145#if defined(__APPLE__)
146 dispatch_semaphore_t _semaphore;
147#elif defined(unix) || defined(__unix) || defined(__unix__)
149#elif defined(_WIN32) || defined(_WIN64)
160 static_assert((StorageSize >=
sizeof(Impl)),
"Semaphore::StorageSize must be increased!");
161 static_assert(((StorageAlign %
alignof(Impl)) == 0),
"Semaphore::StorageAlign must be adjusted!");
170 reinterpret_cast<Impl*
>(&_storage)->~Impl();
Semaphore(int resources)
Default class constructor.
bool TryLock()
Try to acquire semaphore without block.
bool TryLockFor(const Timespan ×pan)
Try to acquire semaphore for the given timespan.
int resources() const noexcept
Get the semaphore resources counter.
void Unlock()
Release semaphore.
void Lock()
Acquire semaphore with block.
Aligned storage validator.
#define throwex
Throw extended exception macro.
Fatal abort execution definition.
#define fatality(...)
Fatal abort execution extended macro.
C++ Common project definitions.
Semaphore synchronization primitive definition.
Aligned storage validator definition.