[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") {
|
||||
// TODO(bwrsandman): Test semaphore, mutex and event
|
||||
REQUIRE(true);
|
||||
WaitResult result;
|
||||
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") {
|
||||
|
|
|
@ -181,6 +181,8 @@ std::unique_ptr<HighResolutionTimer> HighResolutionTimer::CreateRepeating(
|
|||
|
||||
class PosixConditionBase {
|
||||
public:
|
||||
virtual bool Signal() = 0;
|
||||
|
||||
WaitResult Wait(std::chrono::milliseconds timeout) {
|
||||
bool executed;
|
||||
auto predicate = [this] { return this->signaled(); };
|
||||
|
@ -274,7 +276,7 @@ class PosixCondition<Event> : public PosixConditionBase {
|
|||
: signal_(initial_state), manual_reset_(manual_reset) {}
|
||||
virtual ~PosixCondition() = default;
|
||||
|
||||
void Signal() {
|
||||
bool Signal() override {
|
||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||
signal_ = true;
|
||||
if (manual_reset_) {
|
||||
|
@ -282,6 +284,7 @@ class PosixCondition<Event> : public PosixConditionBase {
|
|||
} else {
|
||||
cond_.notify_one();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
|
@ -306,6 +309,8 @@ class PosixCondition<Semaphore> : public PosixConditionBase {
|
|||
PosixCondition(uint32_t initial_count, uint32_t 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) {
|
||||
if (maximum_count_ - count_ >= release_count) {
|
||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||
|
@ -336,6 +341,9 @@ class PosixCondition<Mutant> : public PosixConditionBase {
|
|||
owner_ = std::this_thread::get_id();
|
||||
}
|
||||
}
|
||||
|
||||
bool Signal() override { return Release(); }
|
||||
|
||||
bool Release() {
|
||||
if (owner_ == std::this_thread::get_id() && count_ > 0) {
|
||||
auto lock = std::unique_lock<std::mutex>(mutex_);
|
||||
|
@ -372,6 +380,11 @@ class PosixCondition<Timer> : public PosixConditionBase {
|
|||
|
||||
virtual ~PosixCondition() { Cancel(); }
|
||||
|
||||
bool Signal() override {
|
||||
CompletionRoutine();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(bwrsandman): due_times of under 1ms deadlock under travis
|
||||
bool Set(std::chrono::nanoseconds due_time, std::chrono::milliseconds period,
|
||||
std::function<void()> opt_callback = nullptr) {
|
||||
|
@ -505,6 +518,8 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
}
|
||||
}
|
||||
|
||||
bool Signal() override { return true; }
|
||||
|
||||
std::string name() const {
|
||||
WaitStarted();
|
||||
auto result = std::array<char, 17>{'\0'};
|
||||
|
@ -714,13 +729,16 @@ WaitResult Wait(WaitHandle* wait_handle, bool is_alertable,
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO(dougvj)
|
||||
WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
|
||||
WaitHandle* wait_handle_to_wait_on, bool is_alertable,
|
||||
std::chrono::milliseconds timeout) {
|
||||
assert_always();
|
||||
if (is_alertable) alertable_state_ = true;
|
||||
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;
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue