Merge pull request #4058 from Aestek/fix/netplay-gui-freeze

NetPlay: Fix GUI freeze
This commit is contained in:
Pierre Bourdon 2016-08-01 00:36:49 +02:00 committed by GitHub
commit 2c0364d95c
3 changed files with 51 additions and 17 deletions

View File

@ -326,6 +326,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
// Trusting server for good map value (>=0 && <4) // Trusting server for good map value (>=0 && <4)
// add to pad buffer // add to pad buffer
m_pad_buffer.at(map).Push(pad); m_pad_buffer.at(map).Push(pad);
m_gc_pad_event.Set();
} }
break; break;
@ -344,6 +345,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
// Trusting server for good map value (>=0 && <4) // Trusting server for good map value (>=0 && <4)
// add to Wiimote buffer // add to Wiimote buffer
m_wiimote_buffer.at(map).Push(nw); m_wiimote_buffer.at(map).Push(nw);
m_wii_pad_event.Set();
} }
break; break;
@ -996,15 +998,18 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, GCPadStatus* pad_status)
// Now, we either use the data pushed earlier, or wait for the // Now, we either use the data pushed earlier, or wait for the
// other clients to send it to us // other clients to send it to us
while (!m_pad_buffer[pad_nb].Pop(*pad_status)) while (m_pad_buffer[pad_nb].Size() == 0)
{ {
if (!m_is_running.load()) if (!m_is_running.load())
{
return false; return false;
}
// TODO: use a condition instead of sleeping m_gc_pad_event.Wait();
Common::SleepCurrentThread(1);
} }
m_pad_buffer[pad_nb].Pop(*pad_status);
if (Movie::IsRecordingInput()) if (Movie::IsRecordingInput())
{ {
Movie::RecordInput(pad_status, pad_nb); Movie::RecordInput(pad_status, pad_nb);
@ -1042,14 +1047,19 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
} // unlock players } // unlock players
while (!m_wiimote_buffer[_number].Pop(nw)) while (m_wiimote_buffer[_number].Size() == 0)
{ {
// wait for receiving thread to push some data
Common::SleepCurrentThread(1);
if (!m_is_running.load()) if (!m_is_running.load())
{
return false; return false;
}
// wait for receiving thread to push some data
m_wii_pad_event.Wait();
} }
m_wiimote_buffer[_number].Pop(nw);
// If the reporting mode has changed, we just need to pop through the buffer, // If the reporting mode has changed, we just need to pop through the buffer,
// until we reach a good input // until we reach a good input
if (nw.size() != size) if (nw.size() != size)
@ -1057,12 +1067,19 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
u32 tries = 0; u32 tries = 0;
while (nw.size() != size) while (nw.size() != size)
{ {
while (!m_wiimote_buffer[_number].Pop(nw)) while (m_wiimote_buffer[_number].Size() == 0)
{ {
Common::SleepCurrentThread(1);
if (!m_is_running.load()) if (!m_is_running.load())
{
return false; return false;
}
// wait for receiving thread to push some data
m_wii_pad_event.Wait();
} }
m_wiimote_buffer[_number].Pop(nw);
++tries; ++tries;
if (tries > m_target_buffer_size * 200 / 120) if (tries > m_target_buffer_size * 200 / 120)
break; break;
@ -1083,13 +1100,12 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
// called from ---GUI--- thread and ---NETPLAY--- thread (client side) // called from ---GUI--- thread and ---NETPLAY--- thread (client side)
bool NetPlayClient::StopGame() bool NetPlayClient::StopGame()
{ {
if (!m_is_running.load())
{
PanicAlertT("Game isn't running!");
return false;
}
m_is_running.store(false); m_is_running.store(false);
// stop waiting for input
m_gc_pad_event.Set();
m_wii_pad_event.Set();
NetPlay_Disable(); NetPlay_Disable();
// stop game // stop game
@ -1104,6 +1120,12 @@ void NetPlayClient::Stop()
if (!m_is_running.load()) if (!m_is_running.load())
return; return;
m_is_running.store(false);
// stop waiting for input
m_gc_pad_event.Set();
m_wii_pad_event.Set();
// Tell the server to stop if we have a pad mapped in game. // Tell the server to stop if we have a pad mapped in game.
if (LocalPlayerHasControllerMapped()) if (LocalPlayerHasControllerMapped())
SendStopGamePacket(); SendStopGamePacket();

View File

@ -14,6 +14,7 @@
#include <thread> #include <thread>
#include <vector> #include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Event.h"
#include "Common/FifoQueue.h" #include "Common/FifoQueue.h"
#include "Common/TraversalClient.h" #include "Common/TraversalClient.h"
#include "Core/NetPlayProto.h" #include "Core/NetPlayProto.h"
@ -175,6 +176,8 @@ private:
TraversalClient* m_traversal_client = nullptr; TraversalClient* m_traversal_client = nullptr;
std::thread m_MD5_thread; std::thread m_MD5_thread;
bool m_should_compute_MD5 = false; bool m_should_compute_MD5 = false;
Common::Event m_gc_pad_event;
Common::Event m_wii_pad_event;
u32 m_timebase_frame = 0; u32 m_timebase_frame = 0;
}; };

View File

@ -1132,10 +1132,17 @@ void CFrame::DoStop()
// Pause the state during confirmation and restore it afterwards // Pause the state during confirmation and restore it afterwards
Core::EState state = Core::GetState(); Core::EState state = Core::GetState();
// Do not pause if netplay is running as CPU thread might be blocked
// waiting on inputs
bool should_pause = !NetPlayDialog::GetNetPlayClient();
// If exclusive fullscreen is not enabled then we can pause the emulation // If exclusive fullscreen is not enabled then we can pause the emulation
// before we've exited fullscreen. If not then we need to exit fullscreen first. // before we've exited fullscreen. If not then we need to exit fullscreen first.
if (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() || should_pause =
SConfig::GetInstance().bRenderToMain) should_pause && (!RendererIsFullscreen() || !g_Config.ExclusiveFullscreenEnabled() ||
SConfig::GetInstance().bRenderToMain);
if (should_pause)
{ {
Core::SetState(Core::CORE_PAUSE); Core::SetState(Core::CORE_PAUSE);
} }
@ -1149,7 +1156,9 @@ void CFrame::DoStop()
HotkeyManagerEmu::Enable(true); HotkeyManagerEmu::Enable(true);
if (Ret != wxID_YES) if (Ret != wxID_YES)
{ {
Core::SetState(state); if (should_pause)
Core::SetState(state);
m_confirmStop = false; m_confirmStop = false;
return; return;
} }