12#include <condition_variable>
22 struct Semaphore::Impl {
24 std::condition_variable cv;
28 : _count(initialCount), _maxCount(maximumCount), _name(
""), _hHandle(nullptr), _pImpl(new Impl()) {}
38 static HANDLE
OpenOrCreateWin32Semaphore(
const std::wstring& wsName,
int initialCount,
int maximumCount,
bool openAlways,
bool& bCreatedNew) {
40 HANDLE hHandle = ::CreateSemaphoreW(NULL, initialCount, maximumCount, wsName.c_str());
41 if (hHandle != NULL) {
42 bCreatedNew = (::GetLastError() != ERROR_ALREADY_EXISTS);
45 if (::GetLastError() == ERROR_ACCESS_DENIED) {
54 hHandle = ::OpenSemaphoreW(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, wsName.c_str());
55 if (hHandle == NULL) {
56 if (::GetLastError() == ERROR_ACCESS_DENIED) {
66 : _count(initialCount), _maxCount(maximumCount), _name(sName), _hHandle(nullptr), _pImpl(new Impl()) {
69 if (!_name.IsEmpty()) {
70 std::wstring wsName = Utils::StringConvert::Utf8ToWChar(_name.GetRawString());
71 _hHandle = OpenOrCreateWin32Semaphore(wsName, initialCount, maximumCount, openAlways, bCreatedNew);
83 if (_hHandle !=
nullptr) {
84 ::CloseHandle((HANDLE)_hHandle);
88 if (_pImpl !=
nullptr) {
106 if (sName.
IsEmpty())
return false;
111 HANDLE h = ::OpenSemaphoreW(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, FALSE, wsName.c_str());
112 if (h == NULL)
return false;
115 spSem->_name = sName;
117 pResult = std::move(spSem);
127 if (_hHandle !=
nullptr) {
128 DWORD dwWaitResult = ::WaitForSingleObject((HANDLE)_hHandle, INFINITE);
129 return (dwWaitResult == WAIT_OBJECT_0);
132 if (!_pImpl)
return false;
133 std::unique_lock<std::mutex> lock(_pImpl->mutex);
134 _pImpl->cv.wait(lock, [
this]() {
return _count > 0; });
141 std::unique_lock<std::mutex> lock(pImpl->mutex);
142 bool bRes = pImpl->cv.wait_for(lock, std::chrono::milliseconds(msTimeout), [&count]() {
return count > 0; });
150 std::lock_guard<std::mutex> lock(pImpl->mutex);
151 if (count + releaseCount > maxCount) {
155 count += releaseCount;
156 for (
int i = 0; i < releaseCount; ++i) pImpl->cv.notify_one();
163 if (_hHandle !=
nullptr) {
164 DWORD dwWaitResult = ::WaitForSingleObject((HANDLE)_hHandle, (DWORD)millisecondsTimeout);
165 if (dwWaitResult == WAIT_TIMEOUT) {
168 return (dwWaitResult == WAIT_OBJECT_0);
171 if (!_pImpl)
return false;
178 if (_hHandle !=
nullptr) {
179 LONG previousCount = 0;
180 if (!::ReleaseSemaphore((HANDLE)_hHandle, releaseCount, &previousCount)) {
183 return (
int)previousCount;
186 if (!_pImpl)
return 0;
Represents a Unicode character code point mirroring .NET System.Char.
Limits the number of threads that can access a resource or pool of resources concurrently.
Exception thrown when the Semaphore::Release method is called on a full semaphore.
Provides reference-counted and weak pointer memory management primitives ensuring zero raw ownership.
Utility routines for high-performance UTF-8, UTF-16, and wide-character string conversions.
Defines the exception thrown when the time allotted for a process or operation has expired.
The exception that is thrown when the operating system denies access because of an I/O error or a spe...
Exception thrown when an attempt to open a named system wait handle fails.
A unified smart pointer that supports both unique and shared ownership semantics.
static SmartPointer< T > NewShared()
Creates a Shared SmartPointer, default constructing T.
friend class SmartPointer
Represents text as a sequence of UTF-8 code units with culture-invariant operations.
const char * GetRawString() const
SemaphoreFullException(const String &sMessage)
Initializes a new instance of the SemaphoreFullException class with a specified error message.
bool WaitOne() override
Blocks the current thread until the current WaitHandle receives a signal.
~Semaphore() override
Destructor releasing semaphore resources.
static bool TryOpenExisting(const String &sName, SmartPointer< Semaphore > &pResult)
Opens an existing named system semaphore, and returns a value that indicates whether the operation su...
int Release(int releaseCount=1) override
Exits the semaphore and returns the previous count.
static SmartPointer< Semaphore > OpenExisting(const String &sName)
Opens an existing named system semaphore.
Semaphore(int initialCount, int maximumCount)
Initializes a new instance of the Semaphore class, specifying the initial number of entries and the m...
WaitHandleCannotBeOpenedException(const String &sMessage)
Initializes a new instance of the WaitHandleCannotBeOpenedException class with a specified error mess...
TimeoutException(const String &sMessage)
Initializes a new instance of the TimeoutException class with a specified error message.
UnauthorizedAccessException()
Initializes a new instance of the UnauthorizedAccessException class with a default message.
static std::wstring Utf8ToWChar(const char *pUtf8Str)
Converts a null-terminated UTF-8 char string into a UTF-16 std::wstring.
static bool WaitForSemaphoreCv(Semaphore::Impl *pImpl, int &count, int msTimeout)
static bool s_semDummyCreatedNew
static int ReleaseSemaphoreCv(Semaphore::Impl *pImpl, int &count, int maxCount, int releaseCount)
static HANDLE OpenOrCreateWin32Semaphore(const std::wstring &wsName, int initialCount, int maximumCount, bool openAlways, bool &bCreatedNew)