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
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue