diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index be9231adc..b01b54a5c 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -28,11 +28,6 @@ AudioSystem::AudioSystem(Emulator* emulator) : } AudioSystem::~AudioSystem() { - // TODO(benvanik): thread join. - running_ = false; - xe_thread_release(thread_); - - xe_run_loop_release(run_loop_); } X_STATUS AudioSystem::Setup() { @@ -80,13 +75,15 @@ void AudioSystem::ThreadStart() { //worker_->Pump(); Sleep(1000); + if (!running_) { + break; + } + // Pump audio system. Pump(); } running_ = false; - Shutdown(); - xe_run_loop_release(run_loop); // TODO(benvanik): call module API to kill? @@ -96,6 +93,11 @@ void AudioSystem::Initialize() { } void AudioSystem::Shutdown() { + running_ = false; + xe_thread_join(thread_); + xe_thread_release(thread_); + + xe_run_loop_release(run_loop_); } bool AudioSystem::HandlesRegister(uint64_t addr) { diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index a44a60a5b..9fe552e04 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -33,6 +33,7 @@ public: cpu::Processor* processor() const { return processor_; } virtual X_STATUS Setup(); + virtual void Shutdown(); bool HandlesRegister(uint64_t addr); virtual uint64_t ReadRegister(uint64_t addr); @@ -41,7 +42,6 @@ public: protected: virtual void Initialize(); virtual void Pump() = 0; - virtual void Shutdown(); private: static void ThreadStartThunk(AudioSystem* this_ptr) { diff --git a/src/xenia/apu/nop/nop_audio_system.h b/src/xenia/apu/nop/nop_audio_system.h index db5fe329a..ca82975bd 100644 --- a/src/xenia/apu/nop/nop_audio_system.h +++ b/src/xenia/apu/nop/nop_audio_system.h @@ -26,10 +26,11 @@ public: NopAudioSystem(Emulator* emulator); virtual ~NopAudioSystem(); + virtual void Shutdown(); + protected: virtual void Initialize(); virtual void Pump(); - virtual void Shutdown(); private: }; diff --git a/src/xenia/core/thread.cc b/src/xenia/core/thread.cc index fa2ac36b6..861038890 100644 --- a/src/xenia/core/thread.cc +++ b/src/xenia/core/thread.cc @@ -104,6 +104,11 @@ int xe_thread_start(xe_thread_ref thread) { return 0; } +void xe_thread_join(xe_thread_ref thread) { + HANDLE thread_handle = (HANDLE)thread->handle; + WaitForSingleObject(thread_handle, INFINITE); +} + #else static void* xe_thread_callback_pthreads(void* param) { @@ -137,4 +142,8 @@ int xe_thread_start(xe_thread_ref thread) { return 0; } +void xe_thread_join(xe_thread_ref thread) { + pthread_join((pthread_t)thread->handle, NULL); +} + #endif // WIN32 diff --git a/src/xenia/core/thread.h b/src/xenia/core/thread.h index fee1880cd..1aa8fb0bb 100644 --- a/src/xenia/core/thread.h +++ b/src/xenia/core/thread.h @@ -28,6 +28,7 @@ xe_thread_ref xe_thread_retain(xe_thread_ref thread); void xe_thread_release(xe_thread_ref thread); int xe_thread_start(xe_thread_ref thread); +void xe_thread_join(xe_thread_ref thread); #endif // XENIA_CORE_THREAD_H_ diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 6c77d2399..a14aef311 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -56,8 +56,13 @@ Emulator::~Emulator() { delete file_system_; delete input_system_; + + // Give the systems time to shutdown before we delete them. + graphics_system_->Shutdown(); + audio_system_->Shutdown(); delete graphics_system_; delete audio_system_; + delete processor_; delete debug_server_; diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc index f8c8364d5..842673c0c 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.cc +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.cc @@ -37,9 +37,6 @@ D3D11GraphicsSystem::D3D11GraphicsSystem(Emulator* emulator) : } D3D11GraphicsSystem::~D3D11GraphicsSystem() { - XESAFERELEASE(device_); - XESAFERELEASE(dxgi_factory_); - delete window_; } void D3D11GraphicsSystem::Initialize() { @@ -50,13 +47,13 @@ void D3D11GraphicsSystem::Initialize() { timer_queue_ = CreateTimerQueue(); CreateTimerQueueTimer( - &vsync_timer_, - timer_queue_, - (WAITORTIMERCALLBACK)D3D11GraphicsSystemVsyncCallback, - this, - 16, - 100, - WT_EXECUTEINTIMERTHREAD); + &vsync_timer_, + timer_queue_, + (WAITORTIMERCALLBACK)D3D11GraphicsSystemVsyncCallback, + this, + 16, + 100, + WT_EXECUTEINTIMERTHREAD); // Create DXGI factory so we can get a swap chain/etc. HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), @@ -158,6 +155,8 @@ void D3D11GraphicsSystem::Pump() { } void D3D11GraphicsSystem::Shutdown() { + GraphicsSystem::Shutdown(); + if (vsync_timer_) { DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL); } @@ -165,7 +164,10 @@ void D3D11GraphicsSystem::Shutdown() { DeleteTimerQueueEx(timer_queue_, NULL); } - // TODO(benvanik): release D3D stuff here? - - GraphicsSystem::Shutdown(); + XESAFERELEASE(device_); + device_ = 0; + XESAFERELEASE(dxgi_factory_); + dxgi_factory_ = 0; + delete window_; + window_ = 0; } diff --git a/src/xenia/gpu/d3d11/d3d11_graphics_system.h b/src/xenia/gpu/d3d11/d3d11_graphics_system.h index 8b3420a37..0414d1bb5 100644 --- a/src/xenia/gpu/d3d11/d3d11_graphics_system.h +++ b/src/xenia/gpu/d3d11/d3d11_graphics_system.h @@ -33,10 +33,11 @@ public: D3D11GraphicsSystem(Emulator* emulator); virtual ~D3D11GraphicsSystem(); + virtual void Shutdown(); + protected: virtual void Initialize(); virtual void Pump(); - virtual void Shutdown(); private: IDXGIFactory1* dxgi_factory_; diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index b45eaaf18..90ca71308 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -33,14 +33,6 @@ GraphicsSystem::GraphicsSystem(Emulator* emulator) : } GraphicsSystem::~GraphicsSystem() { - // TODO(benvanik): thread join. - running_ = false; - xe_thread_release(thread_); - - // TODO(benvanik): worker join/etc. - delete worker_; - - xe_run_loop_release(run_loop_); } X_STATUS GraphicsSystem::Setup() { @@ -90,13 +82,15 @@ void GraphicsSystem::ThreadStart() { // Pump worker. worker_->Pump(); + if (!running_) { + break; + } + // Pump graphics system. Pump(); } running_ = false; - Shutdown(); - xe_run_loop_release(run_loop); // TODO(benvanik): call module API to kill? @@ -106,6 +100,13 @@ void GraphicsSystem::Initialize() { } void GraphicsSystem::Shutdown() { + running_ = false; + xe_thread_join(thread_); + xe_thread_release(thread_); + + delete worker_; + + xe_run_loop_release(run_loop_); } void GraphicsSystem::SetInterruptCallback(uint32_t callback, diff --git a/src/xenia/gpu/graphics_system.h b/src/xenia/gpu/graphics_system.h index cb4910d1e..08d00d9b4 100644 --- a/src/xenia/gpu/graphics_system.h +++ b/src/xenia/gpu/graphics_system.h @@ -34,6 +34,7 @@ public: cpu::Processor* processor() const { return processor_; } virtual X_STATUS Setup(); + virtual void Shutdown(); void SetInterruptCallback(uint32_t callback, uint32_t user_data); void InitializeRingBuffer(uint32_t ptr, uint32_t page_count); @@ -51,7 +52,6 @@ public: protected: virtual void Initialize(); virtual void Pump() = 0; - virtual void Shutdown(); private: static void ThreadStartThunk(GraphicsSystem* this_ptr) { diff --git a/src/xenia/gpu/nop/nop_graphics_system.h b/src/xenia/gpu/nop/nop_graphics_system.h index 4ff0579d5..54f77e04e 100644 --- a/src/xenia/gpu/nop/nop_graphics_system.h +++ b/src/xenia/gpu/nop/nop_graphics_system.h @@ -26,10 +26,11 @@ public: NopGraphicsSystem(Emulator* emulator); virtual ~NopGraphicsSystem(); + virtual void Shutdown(); + protected: virtual void Initialize(); virtual void Pump(); - virtual void Shutdown(); private: HANDLE timer_queue_;