Switching std::thread to XThread and hosting in object_refs.
This commit is contained in:
parent
1104f8e687
commit
fff1a7c132
|
@ -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(
|
||||||
this->WorkerThreadMain();
|
emulator()->kernel_state(), 128 * 1024, 0, [this]() {
|
||||||
return 0;
|
this->WorkerThreadMain();
|
||||||
});
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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_;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue