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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,9 @@ namespace kernel {
class KernelState;
template <typename T>
class object_ref;
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
typedef struct {
xe::be<uint32_t> type_flags;
@ -99,6 +102,124 @@ class XObject {
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 xe