[threading linux] Implement Signal and Wait
Add Signal abstract function to handles. Test SignalAndWait.
This commit is contained in:
parent
1ac9ac7cab
commit
d1b3c858e9
|
@ -227,8 +227,19 @@ TEST_CASE("Wait on Multiple Handles", "Wait") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Signal and Wait") {
|
TEST_CASE("Signal and Wait") {
|
||||||
// TODO(bwrsandman): Test semaphore, mutex and event
|
WaitResult result;
|
||||||
REQUIRE(true);
|
auto mutant = Mutant::Create(true);
|
||||||
|
auto event_ = Event::CreateAutoResetEvent(false);
|
||||||
|
auto thread = Thread::Create({}, [&mutant, &event_] {
|
||||||
|
Wait(mutant.get(), false);
|
||||||
|
event_->Set();
|
||||||
|
});
|
||||||
|
result = Wait(event_.get(), false, 50ms);
|
||||||
|
REQUIRE(result == WaitResult::kTimeout);
|
||||||
|
result = SignalAndWait(mutant.get(), event_.get(), false, 50ms);
|
||||||
|
REQUIRE(result == WaitResult::kSuccess);
|
||||||
|
result = Wait(thread.get(), false, 50ms);
|
||||||
|
REQUIRE(result == WaitResult::kSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Wait on Event", "Event") {
|
TEST_CASE("Wait on Event", "Event") {
|
||||||
|
|
|
@ -181,6 +181,8 @@ std::unique_ptr<HighResolutionTimer> HighResolutionTimer::CreateRepeating(
|
||||||
|
|
||||||
class PosixConditionBase {
|
class PosixConditionBase {
|
||||||
public:
|
public:
|
||||||
|
virtual bool Signal() = 0;
|
||||||
|
|
||||||
WaitResult Wait(std::chrono::milliseconds timeout) {
|
WaitResult Wait(std::chrono::milliseconds timeout) {
|
||||||
bool executed;
|
bool executed;
|
||||||
auto predicate = [this] { return this->signaled(); };
|
auto predicate = [this] { return this->signaled(); };
|
||||||
|
@ -274,7 +276,7 @@ class PosixCondition<Event> : public PosixConditionBase {
|
||||||
: signal_(initial_state), manual_reset_(manual_reset) {}
|
: signal_(initial_state), manual_reset_(manual_reset) {}
|
||||||
virtual ~PosixCondition() = default;
|
virtual ~PosixCondition() = default;
|
||||||
|
|
||||||
void Signal() {
|
bool Signal() override {
|
||||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||||
signal_ = true;
|
signal_ = true;
|
||||||
if (manual_reset_) {
|
if (manual_reset_) {
|
||||||
|
@ -282,6 +284,7 @@ class PosixCondition<Event> : public PosixConditionBase {
|
||||||
} else {
|
} else {
|
||||||
cond_.notify_one();
|
cond_.notify_one();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset() {
|
void Reset() {
|
||||||
|
@ -306,6 +309,8 @@ class PosixCondition<Semaphore> : public PosixConditionBase {
|
||||||
PosixCondition(uint32_t initial_count, uint32_t maximum_count)
|
PosixCondition(uint32_t initial_count, uint32_t maximum_count)
|
||||||
: count_(initial_count), maximum_count_(maximum_count) {}
|
: count_(initial_count), maximum_count_(maximum_count) {}
|
||||||
|
|
||||||
|
bool Signal() override { return Release(1, nullptr); }
|
||||||
|
|
||||||
bool Release(uint32_t release_count, int* out_previous_count) {
|
bool Release(uint32_t release_count, int* out_previous_count) {
|
||||||
if (maximum_count_ - count_ >= release_count) {
|
if (maximum_count_ - count_ >= release_count) {
|
||||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||||
|
@ -336,6 +341,9 @@ class PosixCondition<Mutant> : public PosixConditionBase {
|
||||||
owner_ = std::this_thread::get_id();
|
owner_ = std::this_thread::get_id();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Signal() override { return Release(); }
|
||||||
|
|
||||||
bool Release() {
|
bool Release() {
|
||||||
if (owner_ == std::this_thread::get_id() && count_ > 0) {
|
if (owner_ == std::this_thread::get_id() && count_ > 0) {
|
||||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||||
|
@ -372,6 +380,11 @@ class PosixCondition<Timer> : public PosixConditionBase {
|
||||||
|
|
||||||
virtual ~PosixCondition() { Cancel(); }
|
virtual ~PosixCondition() { Cancel(); }
|
||||||
|
|
||||||
|
bool Signal() override {
|
||||||
|
CompletionRoutine();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(bwrsandman): due_times of under 1ms deadlock under travis
|
// TODO(bwrsandman): due_times of under 1ms deadlock under travis
|
||||||
bool Set(std::chrono::nanoseconds due_time, std::chrono::milliseconds period,
|
bool Set(std::chrono::nanoseconds due_time, std::chrono::milliseconds period,
|
||||||
std::function<void()> opt_callback = nullptr) {
|
std::function<void()> opt_callback = nullptr) {
|
||||||
|
@ -505,6 +518,8 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Signal() override { return true; }
|
||||||
|
|
||||||
std::string name() const {
|
std::string name() const {
|
||||||
WaitStarted();
|
WaitStarted();
|
||||||
auto result = std::array<char, 17>{'\0'};
|
auto result = std::array<char, 17>{'\0'};
|
||||||
|
@ -714,13 +729,16 @@ WaitResult Wait(WaitHandle* wait_handle, bool is_alertable,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dougvj)
|
|
||||||
WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
|
WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
|
||||||
WaitHandle* wait_handle_to_wait_on, bool is_alertable,
|
WaitHandle* wait_handle_to_wait_on, bool is_alertable,
|
||||||
std::chrono::milliseconds timeout) {
|
std::chrono::milliseconds timeout) {
|
||||||
assert_always();
|
|
||||||
if (is_alertable) alertable_state_ = true;
|
|
||||||
auto result = WaitResult::kFailed;
|
auto result = WaitResult::kFailed;
|
||||||
|
auto handle_to_signal = reinterpret_cast<PosixConditionBase*>(
|
||||||
|
wait_handle_to_signal->native_handle());
|
||||||
|
auto handle_to_wait_on = reinterpret_cast<PosixConditionBase*>(
|
||||||
|
wait_handle_to_wait_on->native_handle());
|
||||||
|
if (is_alertable) alertable_state_ = true;
|
||||||
|
if (handle_to_signal->Signal()) result = handle_to_wait_on->Wait(timeout);
|
||||||
if (is_alertable) alertable_state_ = false;
|
if (is_alertable) alertable_state_ = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue