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