diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 21476b544..9e39b17a5 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -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 : 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 : public PosixConditionBase { return result; } + void* native_handle() const override { + return reinterpret_cast(timer_); + } + private: inline bool signaled() const override { return signal_; } inline void post_execution() override { @@ -673,6 +681,10 @@ class PosixCondition : public PosixConditionBase { state_ = State::kRunning; } + void* native_handle() const override { + return reinterpret_cast(thread_); + } + private: static void* ThreadStartRoutine(void* parameter); inline bool signaled() const override { return signaled_; } @@ -693,10 +705,15 @@ class PosixCondition : public PosixConditionBase { std::function 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 -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(const_cast*>(&handle_)); - } + PosixConditionBase& condition() override { return handle_; } + void* native_handle() const override { return handle_.native_handle(); } + protected: PosixCondition handle_; friend PosixCondition; }; @@ -738,10 +754,12 @@ PosixConditionHandle::PosixConditionHandle(pthread_t thread) WaitResult Wait(WaitHandle* wait_handle, bool is_alertable, std::chrono::milliseconds timeout) { - auto handle = - reinterpret_cast(wait_handle->native_handle()); + auto posix_wait_handle = dynamic_cast(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( - wait_handle_to_signal->native_handle()); - auto handle_to_wait_on = reinterpret_cast( - wait_handle_to_wait_on->native_handle()); + auto posix_wait_handle_to_signal = + dynamic_cast(wait_handle_to_signal); + auto posix_wait_handle_to_wait_on = + dynamic_cast(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 WaitMultiple(WaitHandle* wait_handles[], size_t wait_handle_count, bool wait_all, bool is_alertable, std::chrono::milliseconds timeout) { - std::vector handles(wait_handle_count); - for (int i = 0u; i < wait_handle_count; ++i) { - handles[i] = - reinterpret_cast(wait_handles[i]->native_handle()); + std::vector conditions; + conditions.reserve(wait_handle_count); + for (size_t i = 0u; i < wait_handle_count; ++i) { + auto handle = dynamic_cast(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; }