[threading linux] Implement native_handle
Move wait implementation to not use native_handle. Implement native_handle for each primitive using posix natives.
This commit is contained in:
parent
e945a13957
commit
d7094fae52
|
@ -253,6 +253,8 @@ class PosixConditionBase {
|
|||
}
|
||||
}
|
||||
|
||||
virtual void* native_handle() const { return cond_.native_handle(); }
|
||||
|
||||
protected:
|
||||
inline virtual bool signaled() const = 0;
|
||||
inline virtual void post_execution() = 0;
|
||||
|
@ -360,6 +362,8 @@ class PosixCondition<Mutant> : public PosixConditionBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
void* native_handle() const override { return mutex_.native_handle(); }
|
||||
|
||||
private:
|
||||
inline bool signaled() const override {
|
||||
return count_ == 0 || owner_ == std::this_thread::get_id();
|
||||
|
@ -440,6 +444,10 @@ class PosixCondition<Timer> : public PosixConditionBase {
|
|||
return result;
|
||||
}
|
||||
|
||||
void* native_handle() const override {
|
||||
return reinterpret_cast<void*>(timer_);
|
||||
}
|
||||
|
||||
private:
|
||||
inline bool signaled() const override { return signal_; }
|
||||
inline void post_execution() override {
|
||||
|
@ -673,6 +681,10 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
state_ = State::kRunning;
|
||||
}
|
||||
|
||||
void* native_handle() const override {
|
||||
return reinterpret_cast<void*>(thread_);
|
||||
}
|
||||
|
||||
private:
|
||||
static void* ThreadStartRoutine(void* parameter);
|
||||
inline bool signaled() const override { return signaled_; }
|
||||
|
@ -693,10 +705,15 @@ class PosixCondition<Thread> : public PosixConditionBase {
|
|||
std::function<void()> user_callback_;
|
||||
};
|
||||
|
||||
class PosixWaitHandle {
|
||||
public:
|
||||
virtual PosixConditionBase& condition() = 0;
|
||||
};
|
||||
|
||||
// This wraps a condition object as our handle because posix has no single
|
||||
// native handle for higher level concurrency constructs such as semaphores
|
||||
template <typename T>
|
||||
class PosixConditionHandle : public T {
|
||||
class PosixConditionHandle : public T, public PosixWaitHandle {
|
||||
public:
|
||||
PosixConditionHandle() = default;
|
||||
explicit PosixConditionHandle(bool);
|
||||
|
@ -705,11 +722,10 @@ class PosixConditionHandle : public T {
|
|||
PosixConditionHandle(uint32_t initial_count, uint32_t maximum_count);
|
||||
~PosixConditionHandle() override = default;
|
||||
|
||||
protected:
|
||||
void* native_handle() const override {
|
||||
return reinterpret_cast<void*>(const_cast<PosixCondition<T>*>(&handle_));
|
||||
}
|
||||
PosixConditionBase& condition() override { return handle_; }
|
||||
void* native_handle() const override { return handle_.native_handle(); }
|
||||
|
||||
protected:
|
||||
PosixCondition<T> handle_;
|
||||
friend PosixCondition<T>;
|
||||
};
|
||||
|
@ -738,10 +754,12 @@ PosixConditionHandle<Thread>::PosixConditionHandle(pthread_t thread)
|
|||
|
||||
WaitResult Wait(WaitHandle* wait_handle, bool is_alertable,
|
||||
std::chrono::milliseconds timeout) {
|
||||
auto handle =
|
||||
reinterpret_cast<PosixConditionBase*>(wait_handle->native_handle());
|
||||
auto posix_wait_handle = dynamic_cast<PosixWaitHandle*>(wait_handle);
|
||||
if (posix_wait_handle == nullptr) {
|
||||
return WaitResult::kFailed;
|
||||
}
|
||||
if (is_alertable) alertable_state_ = true;
|
||||
auto result = handle->Wait(timeout);
|
||||
auto result = posix_wait_handle->condition().Wait(timeout);
|
||||
if (is_alertable) alertable_state_ = false;
|
||||
return result;
|
||||
}
|
||||
|
@ -750,12 +768,18 @@ WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal,
|
|||
WaitHandle* wait_handle_to_wait_on, bool is_alertable,
|
||||
std::chrono::milliseconds timeout) {
|
||||
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());
|
||||
auto posix_wait_handle_to_signal =
|
||||
dynamic_cast<PosixWaitHandle*>(wait_handle_to_signal);
|
||||
auto posix_wait_handle_to_wait_on =
|
||||
dynamic_cast<PosixWaitHandle*>(wait_handle_to_wait_on);
|
||||
if (posix_wait_handle_to_signal == nullptr ||
|
||||
posix_wait_handle_to_wait_on == nullptr) {
|
||||
return WaitResult::kFailed;
|
||||
}
|
||||
if (is_alertable) alertable_state_ = true;
|
||||
if (handle_to_signal->Signal()) result = handle_to_wait_on->Wait(timeout);
|
||||
if (posix_wait_handle_to_signal->condition().Signal()) {
|
||||
result = posix_wait_handle_to_wait_on->condition().Wait(timeout);
|
||||
}
|
||||
if (is_alertable) alertable_state_ = false;
|
||||
return result;
|
||||
}
|
||||
|
@ -764,14 +788,18 @@ std::pair<WaitResult, size_t> WaitMultiple(WaitHandle* wait_handles[],
|
|||
size_t wait_handle_count,
|
||||
bool wait_all, bool is_alertable,
|
||||
std::chrono::milliseconds timeout) {
|
||||
std::vector<PosixConditionBase*> handles(wait_handle_count);
|
||||
for (int i = 0u; i < wait_handle_count; ++i) {
|
||||
handles[i] =
|
||||
reinterpret_cast<PosixConditionBase*>(wait_handles[i]->native_handle());
|
||||
std::vector<PosixConditionBase*> conditions;
|
||||
conditions.reserve(wait_handle_count);
|
||||
for (size_t i = 0u; i < wait_handle_count; ++i) {
|
||||
auto handle = dynamic_cast<PosixWaitHandle*>(wait_handles[i]);
|
||||
if (handle == nullptr) {
|
||||
return std::make_pair(WaitResult::kFailed, 0);
|
||||
}
|
||||
conditions.push_back(&handle->condition());
|
||||
}
|
||||
if (is_alertable) alertable_state_ = true;
|
||||
auto result =
|
||||
PosixConditionBase::WaitMultiple(std::move(handles), wait_all, timeout);
|
||||
auto result = PosixConditionBase::WaitMultiple(std::move(conditions),
|
||||
wait_all, timeout);
|
||||
if (is_alertable) alertable_state_ = false;
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue