BlockingLoop: Yield to UI message pump while waiting.

This commit is contained in:
Jules Blok 2016-11-10 17:55:21 +01:00
parent e8af48adfc
commit 8203ea929b
8 changed files with 56 additions and 1 deletions

View File

@ -148,6 +148,10 @@ void Host_ShowVideoConfig(void*, const std::string&)
{
}
void Host_YieldToUI()
{
}
static bool MsgAlert(const char* caption, const char* text, bool yes_no, int /*Style*/)
{
__android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "%s:%s", caption, text);

View File

@ -66,6 +66,33 @@ public:
m_may_sleep.Set();
}
// Wait for a complete payload run after the last Wakeup() call.
// This version will call a yield function every 100ms.
// If stopped, this returns immediately.
template <class Rep, class Period, typename Functor>
void WaitYield(const std::chrono::duration<Rep, Period>& rel_time, Functor yield_func)
{
// already done
if (IsDone())
return;
// notifying this event will only wake up one thread, so use a mutex here to
// allow only one waiting thread. And in this way, we get an event free wakeup
// but for the first thread for free
std::lock_guard<std::mutex> lk(m_wait_lock);
// Wait for the worker thread to finish.
while (!IsDone())
{
if (!m_done_event.WaitFor(rel_time))
yield_func();
}
// As we wanted to wait for the other thread, there is likely no work remaining.
// So there is no need for a busy loop any more.
m_may_sleep.Set();
}
// Half start the worker.
// So this object is in a running state and Wait() will block until the worker calls Run().
// This may be called from any thread and is supposed to be called at least once before Wait() is

View File

@ -38,6 +38,7 @@ void Host_UpdateDisasmDialog();
void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title);
void Host_ShowVideoConfig(void* parent, const std::string& backend_name);
void Host_YieldToUI();
// TODO (neobrain): Remove this from host!
void* Host_GetRenderHandle();

View File

@ -89,6 +89,9 @@ bool Host_RendererIsFullscreen()
{
return Host::GetInstance()->GetRenderFullscreen();
}
void Host_YieldToUI()
{
}
// We ignore these, and their purpose should be questioned individually.
// In particular, RequestRenderWindowSize, RequestFullscreen, and

View File

@ -10,6 +10,7 @@
#include <wx/app.h>
#include <wx/buffer.h>
#include <wx/cmdline.h>
#include <wx/evtloop.h>
#include <wx/image.h>
#include <wx/imagpng.h>
#include <wx/intl.h>
@ -547,3 +548,8 @@ void Host_ShowVideoConfig(void* parent, const std::string& backend_name)
diag.ShowModal();
}
}
void Host_YieldToUI()
{
wxGetApp().GetMainLoop()->YieldFor(wxEVT_CATEGORY_UI);
}

View File

@ -161,6 +161,10 @@ void Host_ShowVideoConfig(void*, const std::string&)
{
}
void Host_YieldToUI()
{
}
#if HAVE_X11
#include <X11/keysym.h>
#include "DolphinWX/X11Utils.h"

View File

@ -18,6 +18,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/Host.h"
#include "Core/NetPlayProto.h"
#include "VideoCommon/AsyncRequests.h"
@ -94,7 +95,13 @@ void PauseAndLock(bool doLock, bool unpauseOnUnlock)
{
SyncGPU(SyncGPUReason::Other);
EmulatorState(false);
FlushGpu();
const SConfig& param = SConfig::GetInstance();
if (!param.bCPUThread || s_use_deterministic_gpu_thread)
return;
s_gpu_mainloop.WaitYield(std::chrono::milliseconds(100), Host_YieldToUI);
}
else
{

View File

@ -63,6 +63,9 @@ void Host_SetWiiMoteConnectionState(int)
void Host_ShowVideoConfig(void*, const std::string&)
{
}
void Host_YieldToUI()
{
}
std::unique_ptr<cInterfaceBase> HostGL_CreateGLInterface()
{
return nullptr;