Switching std::thread to XThread and hosting in object_refs.

This commit is contained in:
Ben Vanik 2015-05-24 20:22:06 -07:00
parent 1104f8e687
commit fff1a7c132
7 changed files with 152 additions and 28 deletions

View File

@ -104,15 +104,22 @@ X_STATUS AudioSystem::Setup() {
// Threads // Threads
worker_running_ = true; worker_running_ = true;
worker_thread_ = new kernel::XHostThread(emulator()->kernel_state(), worker_thread_ =
128 * 1024, 0, [this]() { kernel::object_ref<kernel::XHostThread>(new kernel::XHostThread(
emulator()->kernel_state(), 128 * 1024, 0, [this]() {
this->WorkerThreadMain(); this->WorkerThreadMain();
return 0; return 0;
}); }));
worker_thread_->Create(); worker_thread_->Create();
decoder_running_ = true; decoder_running_ = true;
decoder_thread_ = std::thread(std::bind(&AudioSystem::DecoderThreadMain, this)); decoder_thread_ =
kernel::object_ref<kernel::XHostThread>(new kernel::XHostThread(
emulator()->kernel_state(), 128 * 1024, 0, [this]() {
DecoderThreadMain();
return 0;
}));
decoder_thread_->Create();
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} }
@ -173,7 +180,6 @@ void AudioSystem::WorkerThreadMain() {
void AudioSystem::DecoderThreadMain() { void AudioSystem::DecoderThreadMain() {
xe::threading::set_name("Audio Decoder"); xe::threading::set_name("Audio Decoder");
xe::Profiler::ThreadEnter("Audio Decoder");
while (decoder_running_) { while (decoder_running_) {
// Wait for the fence // Wait for the fence
@ -315,8 +321,6 @@ void AudioSystem::DecoderThreadMain() {
context.lock.unlock(); context.lock.unlock();
} }
} }
xe::Profiler::ThreadExit();
} }
void AudioSystem::Initialize() {} void AudioSystem::Initialize() {}
@ -325,10 +329,11 @@ void AudioSystem::Shutdown() {
worker_running_ = false; worker_running_ = false;
SetEvent(client_wait_handles_[maximum_client_count_]); SetEvent(client_wait_handles_[maximum_client_count_]);
worker_thread_->Wait(0, 0, 0, nullptr); worker_thread_->Wait(0, 0, 0, nullptr);
worker_thread_->Release(); worker_thread_.reset();
decoder_running_ = false; decoder_running_ = false;
decoder_fence_.Signal(); decoder_fence_.Signal();
worker_thread_.reset();
memory()->SystemHeapFree(registers_.xma_context_array_ptr); memory()->SystemHeapFree(registers_.xma_context_array_ptr);
} }

View File

@ -160,10 +160,10 @@ class AudioSystem {
cpu::Processor* processor_; cpu::Processor* processor_;
std::atomic<bool> worker_running_; std::atomic<bool> worker_running_;
kernel::XHostThread* worker_thread_; kernel::object_ref<kernel::XHostThread> worker_thread_;
std::atomic<bool> decoder_running_; std::atomic<bool> decoder_running_;
std::thread decoder_thread_; kernel::object_ref<kernel::XHostThread> decoder_thread_;
xe::threading::Fence decoder_fence_; xe::threading::Fence decoder_fence_;
std::mutex lock_; std::mutex lock_;

View File

@ -101,11 +101,12 @@ bool CommandProcessor::Initialize(std::unique_ptr<GLContext> context) {
context_ = std::move(context); context_ = std::move(context);
worker_running_ = true; worker_running_ = true;
worker_thread_ = new kernel::XHostThread( worker_thread_ = kernel::object_ref<kernel::XHostThread>(
graphics_system_->emulator()->kernel_state(), 128 * 1024, 0, [this]() { new kernel::XHostThread(graphics_system_->emulator()->kernel_state(),
128 * 1024, 0, [this]() {
WorkerThreadMain(); WorkerThreadMain();
return 0; return 0;
}); }));
worker_thread_->Create(); worker_thread_->Create();
return true; return true;
@ -117,7 +118,7 @@ void CommandProcessor::Shutdown() {
worker_running_ = false; worker_running_ = false;
SetEvent(write_ptr_index_event_); SetEvent(write_ptr_index_event_);
worker_thread_->Wait(0, 0, 0, nullptr); worker_thread_->Wait(0, 0, 0, nullptr);
worker_thread_->Release(); worker_thread_.reset();
all_pipelines_.clear(); all_pipelines_.clear();
all_shaders_.clear(); all_shaders_.clear();
@ -163,7 +164,7 @@ void CommandProcessor::EndTracing() {
void CommandProcessor::CallInThread(std::function<void()> fn) { void CommandProcessor::CallInThread(std::function<void()> fn) {
if (pending_fns_.empty() && if (pending_fns_.empty() &&
worker_thread_ == kernel::XThread::GetCurrentThread()) { worker_thread_.get() == kernel::XThread::GetCurrentThread()) {
fn(); fn();
} else { } else {
pending_fns_.push(std::move(fn)); pending_fns_.push(std::move(fn));

View File

@ -233,7 +233,7 @@ class CommandProcessor {
std::wstring trace_frame_path_; std::wstring trace_frame_path_;
std::atomic<bool> worker_running_; std::atomic<bool> worker_running_;
kernel::XHostThread* worker_thread_; kernel::object_ref<kernel::XHostThread> worker_thread_;
std::unique_ptr<GLContext> context_; std::unique_ptr<GLContext> context_;
SwapHandler swap_handler_; SwapHandler swap_handler_;

View File

@ -45,7 +45,6 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
pcr_address_(0), pcr_address_(0),
thread_state_address_(0), thread_state_address_(0),
thread_state_(0), thread_state_(0),
event_(NULL),
irql_(0) { irql_(0) {
creation_params_.stack_size = stack_size; creation_params_.stack_size = stack_size;
creation_params_.xapi_thread_startup = xapi_thread_startup; creation_params_.xapi_thread_startup = xapi_thread_startup;
@ -63,7 +62,7 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
apc_list_ = new NativeList(kernel_state->memory()); apc_list_ = new NativeList(kernel_state->memory());
event_ = new XEvent(kernel_state); event_ = object_ref<XEvent>(new XEvent(kernel_state));
event_->Initialize(true, false); event_->Initialize(true, false);
// The kernel does not take a reference. We must unregister in the dtor. // The kernel does not take a reference. We must unregister in the dtor.
@ -76,7 +75,7 @@ XThread::~XThread() {
delete apc_list_; delete apc_list_;
event_->Release(); event_.reset();
PlatformDestroy(); PlatformDestroy();
@ -294,13 +293,12 @@ X_STATUS XThread::Exit(int exit_code) {
#if XE_PLATFORM_WIN32 #if XE_PLATFORM_WIN32
static uint32_t __stdcall XThreadStartCallbackWin32(void* param) { static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
XThread* thread = reinterpret_cast<XThread*>(param); auto thread = object_ref<XThread>(reinterpret_cast<XThread*>(param));
thread->set_name(thread->name()); thread->set_name(thread->name());
xe::Profiler::ThreadEnter(thread->name().c_str()); xe::Profiler::ThreadEnter(thread->name().c_str());
current_thread_tls = thread; current_thread_tls = thread.get();
thread->Execute(); thread->Execute();
current_thread_tls = nullptr; current_thread_tls = nullptr;
thread->Release();
xe::Profiler::ThreadExit(); xe::Profiler::ThreadExit();
return 0; return 0;
} }
@ -339,12 +337,11 @@ X_STATUS XThread::PlatformExit(int exit_code) {
#else #else
static void* XThreadStartCallbackPthreads(void* param) { static void* XThreadStartCallbackPthreads(void* param) {
XThread* thread = reinterpret_cast<XThread*>(param); auto thread = object_ref<XThread>(reinterpret_cast<XThread*>(param));
xe::Profiler::ThreadEnter(thread->name().c_str()); xe::Profiler::ThreadEnter(thread->name().c_str());
current_thread_tls = thread; current_thread_tls = thread.get();
thread->Execute(); thread->Execute();
current_thread_tls = nullptr; current_thread_tls = nullptr;
thread->Release();
xe::Profiler::ThreadExit(); xe::Profiler::ThreadExit();
return 0; return 0;
} }

View File

@ -100,7 +100,7 @@ class XThread : public XObject {
std::mutex apc_lock_; std::mutex apc_lock_;
NativeList* apc_list_; NativeList* apc_list_;
XEvent* event_; object_ref<XEvent> event_;
}; };
class XHostThread : public XThread { class XHostThread : public XThread {

View File

@ -24,6 +24,9 @@ namespace kernel {
class KernelState; class KernelState;
template <typename T>
class object_ref;
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html // http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
typedef struct { typedef struct {
xe::be<uint32_t> type_flags; xe::be<uint32_t> type_flags;
@ -99,6 +102,124 @@ class XObject {
std::string name_; // May be zero length. std::string name_; // May be zero length.
}; };
template <typename T>
class object_ref {
public:
object_ref() noexcept : value_(nullptr) {}
object_ref(nullptr_t) noexcept : value_(nullptr) {}
object_ref& operator=(nullptr_t) noexcept {
reset();
return (*this);
}
explicit object_ref(T* value) noexcept : value_(value) {
// Assumes retained on call.
}
explicit object_ref(const object_ref& right) noexcept {
reset(right.get());
if (value_) value_->Retain();
}
template <class V, class = typename std::enable_if<
std::is_convertible<V*, T*>::value, void>::type>
object_ref(const object_ref<V>& right) noexcept {
reset(right.get());
if (value_) value_->Retain();
}
object_ref(object_ref&& right) noexcept : value_(right.release()) {}
object_ref& operator=(object_ref&& right) noexcept {
object_ref(std::move(right)).swap(*this);
return (*this);
}
template <typename V>
object_ref& operator=(object_ref<V>&& right) noexcept {
object_ref(std::move(right)).swap(*this);
return (*this);
}
object_ref& operator=(const object_ref& right) noexcept {
object_ref(right).swap(*this);
return (*this);
}
template <typename V>
object_ref& operator=(const object_ref<V>& right) noexcept {
object_ref(right).swap(*this);
return (*this);
}
void swap(object_ref& right) noexcept {
std::_Swap_adl(value_, right.value_);
}
~object_ref() noexcept {
if (value_) {
value_->Release();
value_ = nullptr;
}
}
typename std::add_lvalue_reference<T>::type operator*() const {
return (*get());
}
T* operator->() const noexcept {
return std::pointer_traits<T*>::pointer_to(**this);
}
T* get() const noexcept { return value_; }
template <typename V>
V* get() const noexcept {
return reinterpret_cast<V*>(value_);
}
explicit operator bool() const noexcept { return value_ != nullptr; }
T* release() noexcept {
T* value = value_;
value_ = nullptr;
return value;
}
static void accept(T* value) {
reset(value);
value->Release();
}
void reset() noexcept { object_ref().swap(*this); }
void reset(T* value) noexcept { object_ref(value).swap(*this); }
private:
T* value_ = nullptr;
};
template <class _Ty>
bool operator==(const object_ref<_Ty>& _Left, nullptr_t) noexcept {
return (_Left.get() == (_Ty*)0);
}
template <class _Ty>
bool operator==(nullptr_t, const object_ref<_Ty>& _Right) noexcept {
return ((_Ty*)0 == _Right.get());
}
template <class _Ty>
bool operator!=(const object_ref<_Ty>& _Left, nullptr_t _Right) noexcept {
return (!(_Left == _Right));
}
template <class _Ty>
bool operator!=(nullptr_t _Left, const object_ref<_Ty>& _Right) noexcept {
return (!(_Left == _Right));
}
template <typename T>
object_ref<T> retain_object(T* ptr) {
if (ptr) ptr->Retain();
return object_ref<T>(ptr);
}
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe