-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
33c8301
commit 280c099
Showing
5 changed files
with
151 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#prafma once | ||
#include "../../../include/xtd/threading/semaphore.h" | ||
#define __XTD_CORE_NATIVE_LIBRARY__ | ||
#include <xtd/native/named_semaphore.h> | ||
#undef __XTD_CORE_NATIVE_LIBRARY__ | ||
|
||
class xtd::threading::semaphore::named_semaphore : public semaphore_base { | ||
public: | ||
~named_semaphore() {destroy();} | ||
|
||
intptr handle() const noexcept override { | ||
return handle_; | ||
} | ||
|
||
void handle(intptr value) override { | ||
handle_ = value; | ||
} | ||
|
||
bool create(int32 initial_count, int32 maximum_count) override { | ||
throw invalid_operation_exception {csf_}; | ||
} | ||
|
||
bool create(int32 initial_count, int32 maximum_count, const ustring& name) override { | ||
name_ = name; | ||
handle_ = native::named_semaphore::create(initial_count, maximum_count, name); | ||
return handle_ != invalid_handle; | ||
} | ||
|
||
void destroy() override { | ||
if (handle_ == invalid_handle) return; | ||
native::named_semaphore::destroy(handle_, name_); | ||
handle_ = invalid_handle; | ||
} | ||
|
||
bool open(const ustring& name) override { | ||
name_ = name; | ||
handle_ = native::named_semaphore::open(name); | ||
return handle_ != invalid_handle; | ||
} | ||
|
||
bool signal(bool& io_error, int32 release_count, int32& previous_count) override { | ||
io_error = false; | ||
return native::named_semaphore::signal(handle_, release_count, previous_count, io_error); | ||
} | ||
|
||
uint32 wait(int32 milliseconds_timeout) override { | ||
return native::named_semaphore::wait(handle_, milliseconds_timeout); | ||
} | ||
|
||
private: | ||
intptr handle_ = invalid_handle; | ||
ustring name_; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#pragma once | ||
#include "../../../include/xtd/threading/semaphore.h" | ||
|
||
class xtd::threading::semaphore::semaphore_base { | ||
public: | ||
virtual ~semaphore_base() = default; | ||
|
||
virtual intptr handle() const noexcept = 0; | ||
virtual void handle(intptr value) = 0; | ||
virtual bool create(int32 initial_count, int32 maximum_count) = 0; | ||
virtual bool create(int32 initial_count, int32 maximum_count, const ustring& name) = 0; | ||
virtual void destroy() = 0; | ||
virtual bool open(const ustring& name) = 0; | ||
virtual bool signal(bool& io_error, int32 release_count, int32& previous_count) = 0; | ||
virtual uint32 wait(int32 milliseconds_timeout) = 0; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
#pragma once | ||
#include "../../../include/xtd/threading/semaphore.h" | ||
#include <condition_variable> | ||
#include <mutex> | ||
|
||
class xtd::threading::semaphore::unnamed_semaphore : public semaphore_base { | ||
public: | ||
~unnamed_semaphore() {destroy();} | ||
|
||
intptr handle() const noexcept override { | ||
return handle_ ? reinterpret_cast<intptr>(handle_.get()) : invalid_handle; | ||
} | ||
|
||
void handle(intptr value) override { | ||
throw invalid_operation_exception {csf_}; | ||
} | ||
|
||
bool create(int32 initial_count, int32 maximum_count) override { | ||
handle_ = std::make_shared<data>(); | ||
handle_->maximum_count = maximum_count; | ||
uint32 error = 0; | ||
for (auto index = 0; !error && index < initial_count; ++index) | ||
error = wait(-1); | ||
if (error) return false; | ||
return true; | ||
} | ||
|
||
bool create(int32 initial_count, int32 maximum_count, const ustring& name) override { | ||
throw invalid_operation_exception {csf_}; | ||
} | ||
|
||
void destroy() override { | ||
if (!handle_) return; | ||
handle_.reset(); | ||
} | ||
|
||
bool open(const ustring& name) override { | ||
throw invalid_operation_exception {csf_}; | ||
} | ||
|
||
bool signal(bool& io_error, int32 release_count, int32& previous_count) override { | ||
std::unique_lock<std::mutex> lock(handle_->mutex); | ||
previous_count = handle_->count; | ||
for (int count = 0; count < release_count; ++count) { | ||
if (handle_->count + 1 >= handle_->maximum_count) { | ||
io_error = true; | ||
return false; | ||
} | ||
handle_->count++; | ||
handle_->condition.notify_one(); | ||
} | ||
return true; | ||
} | ||
|
||
uint32 wait(int32 milliseconds_timeout) override { | ||
std::unique_lock<std::mutex> lock(handle_->mutex); | ||
if (handle_->count == 0) return 0xFFFFFFFF; | ||
|
||
if (milliseconds_timeout == -1) { | ||
handle_->condition.wait(lock); | ||
handle_->count--; | ||
return 0x00000000; | ||
} | ||
if (handle_->condition.wait_for(lock, std::chrono::milliseconds {milliseconds_timeout}) == std::cv_status::timeout) return 0x00000102; | ||
handle_->count--; | ||
return 0x00000000; | ||
} | ||
|
||
private: | ||
struct data { | ||
std::condition_variable condition; | ||
int count = 0; | ||
int maximum_count = std::numeric_limits<int>::max(); | ||
std::mutex mutex; | ||
}; | ||
std::shared_ptr<data> handle_; | ||
}; |