mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 06:39:46 -06:00
Replaced Common::Thread with a partial implementation of std::thread. (rvalue references are used if available, <thread> is used if possible) Eliminates the need to use dynamic memory allocation for threads, so it's impossible to forget to delete a thread or set a pointer to NULL. Enables use of type-safe thread functions, no need to cast to and from void*. I've made sure the code compiles in vs08 and tested the functionality of "StdThread.h" on Linux so I'm hoping everything will work :p. In the future "StdThread.h" can be removed (maybe when OS X ships with gcc 4.4 and vs2015 is released :p).
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6933 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -95,7 +95,7 @@ TPeekMessages Callback_PeekMessages = NULL;
|
||||
TUpdateFPSDisplay g_pUpdateFPSDisplay = NULL;
|
||||
|
||||
// Function declarations
|
||||
THREAD_RETURN EmuThread(void *pArg);
|
||||
void EmuThread();
|
||||
|
||||
void Stop();
|
||||
|
||||
@ -104,9 +104,9 @@ bool g_bHwInit = false;
|
||||
bool g_bRealWiimote = false;
|
||||
void *g_pWindowHandle = NULL;
|
||||
|
||||
Common::Thread* g_EmuThread = NULL;
|
||||
std::thread g_EmuThread;
|
||||
|
||||
static Common::Thread* cpuThread = NULL;
|
||||
static std::thread cpuThread;
|
||||
|
||||
SCoreStartupParameter g_CoreStartupParameter;
|
||||
|
||||
@ -122,7 +122,7 @@ Common::Event cpuRunloopQuit;
|
||||
std::string StopMessage(bool bMainThread, std::string Message)
|
||||
{
|
||||
return StringFromFormat("Stop [%s %i]\t%s\t%s",
|
||||
bMainThread ? "Main Thread" : "Video Thread", Common::Thread::CurrentId(), MemUsage().c_str(), Message.c_str());
|
||||
bMainThread ? "Main Thread" : "Video Thread", Common::CurrentThreadId(), MemUsage().c_str(), Message.c_str());
|
||||
}
|
||||
|
||||
//
|
||||
@ -166,14 +166,14 @@ bool isRunning()
|
||||
|
||||
bool IsRunningInCurrentThread()
|
||||
{
|
||||
return isRunning() && ((cpuThread == NULL) || cpuThread->IsCurrentThread());
|
||||
return isRunning() && ((cpuThread.joinable()) || cpuThread.get_id() == std::this_thread::get_id());
|
||||
}
|
||||
|
||||
// This is called from the GUI thread. See the booting call schedule in
|
||||
// BootManager.cpp
|
||||
bool Init()
|
||||
{
|
||||
if (g_EmuThread != NULL)
|
||||
if (g_EmuThread.joinable())
|
||||
{
|
||||
PanicAlertT("Emu Thread already running");
|
||||
return false;
|
||||
@ -195,7 +195,7 @@ bool Init()
|
||||
emuThreadGoing.Init();
|
||||
|
||||
// Start the emu thread
|
||||
g_EmuThread = new Common::Thread(EmuThread, NULL);
|
||||
g_EmuThread = std::thread(EmuThread);
|
||||
|
||||
// Wait until the emu thread is running
|
||||
emuThreadGoing.MsgWait();
|
||||
@ -242,14 +242,12 @@ void Stop() // - Hammertime!
|
||||
Host_SetWaitCursor(false);
|
||||
|
||||
WARN_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str());
|
||||
g_EmuThread->WaitForDeath();
|
||||
delete g_EmuThread; // Wait for emuthread to close.
|
||||
g_EmuThread = 0;
|
||||
g_EmuThread.join(); // Wait for emuthread to close.
|
||||
}
|
||||
|
||||
// Create the CPU thread. which would be a CPU + Video thread in Single Core mode.
|
||||
|
||||
THREAD_RETURN CpuThread(void *pArg)
|
||||
void CpuThread()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
@ -269,7 +267,7 @@ THREAD_RETURN CpuThread(void *pArg)
|
||||
}
|
||||
|
||||
if (_CoreParameter.bLockThreads)
|
||||
Common::Thread::SetCurrentThreadAffinity(1); // Force to first core
|
||||
Common::SetCurrentThreadAffinity(1); // Force to first core
|
||||
|
||||
if (_CoreParameter.bUseFastMem)
|
||||
{
|
||||
@ -296,13 +294,13 @@ THREAD_RETURN CpuThread(void *pArg)
|
||||
#ifdef __APPLE__
|
||||
[pool release];
|
||||
#endif
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Initalize plugins and create emulation thread
|
||||
// Call browser: Init():g_EmuThread(). See the BootManager.cpp file description for a complete call schedule.
|
||||
THREAD_RETURN EmuThread(void *pArg)
|
||||
void EmuThread()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
@ -319,9 +317,9 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
if (_CoreParameter.bLockThreads)
|
||||
{
|
||||
if (cpu_info.num_cores > 3)
|
||||
Common::Thread::SetCurrentThreadAffinity(4); // Force to third, non-HT core
|
||||
Common::SetCurrentThreadAffinity(4); // Force to third, non-HT core
|
||||
else
|
||||
Common::Thread::SetCurrentThreadAffinity(2); // Force to second core
|
||||
Common::SetCurrentThreadAffinity(2); // Force to second core
|
||||
}
|
||||
|
||||
INFO_LOG(OSREPORT, "Starting core = %s mode", _CoreParameter.bWii ? "Wii" : "Gamecube");
|
||||
@ -420,7 +418,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
|
||||
|
||||
// Spawn the CPU thread
|
||||
_dbg_assert_(OSHLE, cpuThread == NULL);
|
||||
_dbg_assert_(OSHLE, !cpuThread.joinable());
|
||||
// ENTER THE VIDEO THREAD LOOP
|
||||
if (_CoreParameter.bCPUThread)
|
||||
{
|
||||
@ -428,7 +426,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
// and then takes over and becomes the video thread
|
||||
|
||||
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
|
||||
cpuThread = new Common::Thread(CpuThread, pArg);
|
||||
cpuThread = std::thread(CpuThread);
|
||||
Common::SetCurrentThreadName("Video thread");
|
||||
|
||||
// Update the window again because all stuff is initialized
|
||||
@ -444,7 +442,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
// Without this extra thread, the video plugin window hangs in single
|
||||
// core mode since noone is pumping messages.
|
||||
|
||||
cpuThread = new Common::Thread(CpuThread, pArg);
|
||||
cpuThread = std::thread(CpuThread);
|
||||
Common::SetCurrentThreadName("Emuthread - Idle");
|
||||
|
||||
// Update the window again because all stuff is initialized
|
||||
@ -475,13 +473,10 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
|
||||
// At this point, the CpuThread has already returned in SC mode.
|
||||
// But it may still be waiting in Dual Core mode.
|
||||
if (cpuThread)
|
||||
if (cpuThread.joinable())
|
||||
{
|
||||
// There is a CPU thread - join it.
|
||||
cpuThread->WaitForDeath();
|
||||
delete cpuThread;
|
||||
// Returns after game exited
|
||||
cpuThread = NULL;
|
||||
cpuThread.join();
|
||||
}
|
||||
|
||||
VolumeHandler::EjectVolume();
|
||||
@ -517,7 +512,6 @@ THREAD_RETURN EmuThread(void *pArg)
|
||||
#ifdef __APPLE__
|
||||
[pool release];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set or get the running state
|
||||
|
@ -19,45 +19,41 @@
|
||||
#include "EXI_DeviceGecko.h"
|
||||
#include "../Core.h"
|
||||
|
||||
THREAD_RETURN ClientThreadFunc(void *arg)
|
||||
void ClientThreadFunc(GeckoSockServer *arg)
|
||||
{
|
||||
((GeckoSockServer*)arg)->ClientThread();
|
||||
return 0;
|
||||
arg->ClientThread();
|
||||
}
|
||||
|
||||
u16 GeckoSockServer::server_port;
|
||||
int GeckoSockServer::client_count;
|
||||
Common::Thread *GeckoSockServer::connectionThread = NULL;
|
||||
std::thread GeckoSockServer::connectionThread;
|
||||
volatile bool GeckoSockServer::server_running;
|
||||
std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks;
|
||||
Common::CriticalSection GeckoSockServer::connection_lock;
|
||||
|
||||
GeckoSockServer::GeckoSockServer()
|
||||
: clientThread(NULL)
|
||||
, client_running(false)
|
||||
: client_running(false)
|
||||
{
|
||||
if (!connectionThread)
|
||||
connectionThread = new Common::Thread(&GeckoConnectionWaiter, (void*)0);
|
||||
if (!connectionThread.joinable())
|
||||
connectionThread = std::thread(GeckoConnectionWaiter);
|
||||
}
|
||||
|
||||
GeckoSockServer::~GeckoSockServer()
|
||||
{
|
||||
if (clientThread)
|
||||
if (clientThread.joinable())
|
||||
--client_count;
|
||||
|
||||
client_running = false;
|
||||
delete clientThread;
|
||||
clientThread = NULL;
|
||||
clientThread.join();
|
||||
|
||||
if (client_count <= 0)
|
||||
{
|
||||
server_running = false;
|
||||
delete connectionThread;
|
||||
connectionThread = NULL;
|
||||
connectionThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
|
||||
void GeckoSockServer::GeckoConnectionWaiter()
|
||||
{
|
||||
Common::SetCurrentThreadName("Gecko Connection Waiter");
|
||||
|
||||
@ -70,7 +66,7 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
|
||||
}
|
||||
|
||||
if (!server_running)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
Core::DisplayMessage(
|
||||
StringFromFormat("USBGecko: Listening on TCP port %u", server_port),
|
||||
@ -90,7 +86,6 @@ THREAD_RETURN GeckoSockServer::GeckoConnectionWaiter(void*)
|
||||
SLEEP(1);
|
||||
}
|
||||
server.Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
|
||||
@ -101,15 +96,15 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
|
||||
if (waiting_socks.size())
|
||||
{
|
||||
sock_to_fill = waiting_socks.front();
|
||||
if (clientThread)
|
||||
if (clientThread.joinable())
|
||||
{
|
||||
client_running = false;
|
||||
delete clientThread;
|
||||
clientThread = NULL;
|
||||
clientThread.join();
|
||||
|
||||
recv_fifo = std::queue<u8>();
|
||||
send_fifo = std::queue<u8>();
|
||||
}
|
||||
clientThread = new Common::Thread(ClientThreadFunc, this);
|
||||
clientThread = std::thread(ClientThreadFunc, this);
|
||||
client_count++;
|
||||
waiting_socks.pop();
|
||||
sock_filled = true;
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
// Client for this server object
|
||||
sf::SocketTCP client;
|
||||
void ClientThread();
|
||||
Common::Thread *clientThread;
|
||||
std::thread clientThread;
|
||||
Common::CriticalSection transfer_lock;
|
||||
|
||||
std::queue<u8> send_fifo;
|
||||
@ -44,11 +44,11 @@ private:
|
||||
volatile bool client_running;
|
||||
|
||||
// Only ever one server thread
|
||||
static THREAD_RETURN GeckoConnectionWaiter(void*);
|
||||
static void GeckoConnectionWaiter();
|
||||
|
||||
static u16 server_port;
|
||||
static volatile bool server_running;
|
||||
static Common::Thread *connectionThread;
|
||||
static std::thread connectionThread;
|
||||
static std::queue<sf::SocketTCP> waiting_socks;
|
||||
static Common::CriticalSection connection_lock;
|
||||
};
|
||||
|
@ -46,8 +46,7 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
|
||||
CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int _card_index) :
|
||||
m_strFilename(_rFilename),
|
||||
card_index(_card_index),
|
||||
m_bDirty(false),
|
||||
flushThread(NULL)
|
||||
m_bDirty(false)
|
||||
{
|
||||
cards[_card_index] = this;
|
||||
et_this_card = CoreTiming::RegisterEvent(_rName.c_str(), FlushCallback);
|
||||
@ -103,9 +102,8 @@ CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rF
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN innerFlush(void *pArgs)
|
||||
void innerFlush(flushStruct* data)
|
||||
{
|
||||
flushStruct *data = ((flushStruct *)pArgs);
|
||||
FILE* pFile = NULL;
|
||||
pFile = fopen(data->filename.c_str(), "wb");
|
||||
|
||||
@ -123,7 +121,7 @@ THREAD_RETURN innerFlush(void *pArgs)
|
||||
PanicAlertT("Could not write memory card file %s.\n\n"
|
||||
"Are you running Dolphin from a CD/DVD, or is the save file maybe write protected?", data->filename.c_str());
|
||||
delete data;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(data->memcardContent, data->memcardSize, 1, pFile);
|
||||
@ -134,7 +132,7 @@ THREAD_RETURN innerFlush(void *pArgs)
|
||||
data->filename.c_str()).c_str(), 4000);
|
||||
|
||||
delete data;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Flush memory card contents to disc
|
||||
@ -143,10 +141,9 @@ void CEXIMemoryCard::Flush(bool exiting)
|
||||
if(!m_bDirty)
|
||||
return;
|
||||
|
||||
if(flushThread)
|
||||
if (flushThread.joinable())
|
||||
{
|
||||
delete flushThread;
|
||||
flushThread = NULL;
|
||||
flushThread.join();
|
||||
}
|
||||
|
||||
if(!exiting)
|
||||
@ -159,9 +156,9 @@ void CEXIMemoryCard::Flush(bool exiting)
|
||||
fs->memcardSize = memory_card_size;
|
||||
fs->bExiting = exiting;
|
||||
|
||||
flushThread = new Common::Thread(innerFlush, fs);
|
||||
if(exiting)
|
||||
flushThread->WaitForDeath();
|
||||
flushThread = std::thread(innerFlush, fs);
|
||||
if (exiting)
|
||||
flushThread.join();
|
||||
|
||||
m_bDirty = false;
|
||||
}
|
||||
@ -171,10 +168,10 @@ CEXIMemoryCard::~CEXIMemoryCard()
|
||||
Flush(true);
|
||||
delete[] memory_card_content;
|
||||
memory_card_content = NULL;
|
||||
if(flushThread)
|
||||
|
||||
if (flushThread.joinable())
|
||||
{
|
||||
delete flushThread;
|
||||
flushThread = NULL;
|
||||
flushThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,10 +183,9 @@ bool CEXIMemoryCard::IsPresent()
|
||||
void CEXIMemoryCard::SetCS(int cs)
|
||||
{
|
||||
// So that memory card won't be invalidated during flushing
|
||||
if(flushThread)
|
||||
if (flushThread.joinable())
|
||||
{
|
||||
delete flushThread;
|
||||
flushThread = NULL;
|
||||
flushThread.join();
|
||||
}
|
||||
|
||||
if (cs) // not-selected to selected
|
||||
|
@ -90,7 +90,7 @@ private:
|
||||
int memory_card_size; //! in bytes, must be power of 2.
|
||||
u8 *memory_card_content;
|
||||
|
||||
Common::Thread *flushThread;
|
||||
std::thread flushThread;
|
||||
|
||||
protected:
|
||||
virtual void TransferByte(u8 &byte);
|
||||
|
@ -22,14 +22,14 @@
|
||||
#include "Thread.h"
|
||||
#include <queue>
|
||||
|
||||
static Common::Thread *connectionThread = NULL;
|
||||
static std::thread connectionThread;
|
||||
static std::queue<sf::SocketTCP> waiting_socks;
|
||||
static Common::CriticalSection cs_gba;
|
||||
namespace { volatile bool server_running; }
|
||||
|
||||
// --- GameBoy Advance "Link Cable" ---
|
||||
|
||||
THREAD_RETURN GBAConnectionWaiter(void*)
|
||||
void GBAConnectionWaiter()
|
||||
{
|
||||
server_running = true;
|
||||
|
||||
@ -38,7 +38,7 @@ THREAD_RETURN GBAConnectionWaiter(void*)
|
||||
sf::SocketTCP server;
|
||||
// "dolphin gba"
|
||||
if (!server.Listen(0xd6ba))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
server.SetBlocking(false);
|
||||
|
||||
@ -54,14 +54,14 @@ THREAD_RETURN GBAConnectionWaiter(void*)
|
||||
SLEEP(1);
|
||||
}
|
||||
server.Close();
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
void GBAConnectionWaiter_Shutdown()
|
||||
{
|
||||
server_running = false;
|
||||
delete connectionThread;
|
||||
connectionThread = NULL;
|
||||
if (connectionThread.joinable())
|
||||
connectionThread.join();
|
||||
}
|
||||
|
||||
bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
|
||||
@ -82,8 +82,8 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
|
||||
|
||||
GBASockServer::GBASockServer()
|
||||
{
|
||||
if (!connectionThread)
|
||||
connectionThread = new Common::Thread(GBAConnectionWaiter, (void*)0);
|
||||
if (!connectionThread.joinable())
|
||||
connectionThread = std::thread(GBAConnectionWaiter);
|
||||
}
|
||||
|
||||
GBASockServer::~GBASockServer()
|
||||
|
@ -41,10 +41,10 @@ bool g_real_wiimotes_initialized = false;
|
||||
unsigned int g_wiimotes_found = 0;
|
||||
|
||||
volatile bool g_run_wiimote_thread = false;
|
||||
Common::Thread *g_wiimote_threads[MAX_WIIMOTES] = {};
|
||||
std::thread g_wiimote_threads[MAX_WIIMOTES] = {};
|
||||
Common::CriticalSection g_refresh_critsec;
|
||||
|
||||
THREAD_RETURN WiimoteThreadFunc(void* arg);
|
||||
void WiimoteThreadFunc(Wiimote& arg);
|
||||
void StartWiimoteThreads();
|
||||
void StopWiimoteThreads();
|
||||
|
||||
@ -433,10 +433,10 @@ void Refresh()
|
||||
if (g_wiimotes[i] && (!(WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ||
|
||||
!g_wiimotes[i]->IsConnected()))
|
||||
{
|
||||
// TODO: this looks broken
|
||||
delete g_wiimotes[i];
|
||||
g_wiimotes[i] = NULL;
|
||||
delete g_wiimote_threads[i];
|
||||
g_wiimote_threads[i] = NULL;
|
||||
g_wiimote_threads[i].join();
|
||||
--g_wiimotes_found;
|
||||
}
|
||||
|
||||
@ -510,57 +510,51 @@ void StartWiimoteThreads()
|
||||
{
|
||||
g_run_wiimote_thread = true;
|
||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
if (g_wiimotes[i] && !g_wiimote_threads[i])
|
||||
g_wiimote_threads[i] = new Common::Thread(WiimoteThreadFunc, g_wiimotes[i]);
|
||||
if (g_wiimotes[i])
|
||||
g_wiimote_threads[i] = std::thread(WiimoteThreadFunc, *g_wiimotes[i]);
|
||||
}
|
||||
|
||||
void StopWiimoteThreads()
|
||||
{
|
||||
g_run_wiimote_thread = false;
|
||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
if (g_wiimote_threads[i])
|
||||
{
|
||||
delete g_wiimote_threads[i];
|
||||
g_wiimote_threads[i] = NULL;
|
||||
}
|
||||
if (g_wiimote_threads[i].joinable())
|
||||
g_wiimote_threads[i].join();
|
||||
}
|
||||
|
||||
THREAD_RETURN WiimoteThreadFunc(void* arg)
|
||||
void WiimoteThreadFunc(Wiimote& wiimote)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
#endif
|
||||
|
||||
Wiimote* const wiimote = (Wiimote*)arg;
|
||||
|
||||
char thname[] = "Wiimote # Thread";
|
||||
thname[8] = (char)('1' + wiimote->index);
|
||||
thname[8] = (char)('1' + wiimote.index);
|
||||
Common::SetCurrentThreadName(thname);
|
||||
|
||||
// rumble briefly
|
||||
wiimote->Rumble();
|
||||
wiimote.Rumble();
|
||||
|
||||
Host_ConnectWiimote(wiimote->index, true);
|
||||
Host_ConnectWiimote(wiimote.index, true);
|
||||
|
||||
// main loop
|
||||
while (g_run_wiimote_thread && wiimote->IsConnected())
|
||||
while (g_run_wiimote_thread && wiimote.IsConnected())
|
||||
{
|
||||
// hopefully this is alright
|
||||
while (wiimote->Write()) {}
|
||||
while (wiimote.Write()) {}
|
||||
|
||||
#ifndef __APPLE__
|
||||
// sleep if there was nothing to read
|
||||
if (false == wiimote->Read())
|
||||
if (false == wiimote.Read())
|
||||
#endif
|
||||
Common::SleepCurrentThread(1);
|
||||
}
|
||||
|
||||
Host_ConnectWiimote(wiimote->index, false);
|
||||
Host_ConnectWiimote(wiimote.index, false);
|
||||
|
||||
#ifdef __APPLE__
|
||||
[pool release];
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
}; // end of namespace
|
||||
|
@ -69,7 +69,7 @@ static u8 *undoLoad = NULL;
|
||||
|
||||
static bool const bCompressed = true;
|
||||
|
||||
static Common::Thread *saveThread = NULL;
|
||||
static std::thread saveThread;
|
||||
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
@ -159,9 +159,8 @@ void VerifyBufferStateCallback(u64 userdata, int cyclesLate)
|
||||
state_op_in_progress = false;
|
||||
}
|
||||
|
||||
THREAD_RETURN CompressAndDumpState(void *pArgs)
|
||||
void CompressAndDumpState(saveStruct* saveArg)
|
||||
{
|
||||
saveStruct *saveArg = (saveStruct *)pArgs;
|
||||
u8 *buffer = saveArg->buffer;
|
||||
size_t sz = saveArg->size;
|
||||
lzo_uint out_len = 0;
|
||||
@ -185,7 +184,7 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
|
||||
{
|
||||
Core::DisplayMessage("Could not save state", 2000);
|
||||
delete[] buffer;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Setting up the header
|
||||
@ -229,7 +228,6 @@ THREAD_RETURN CompressAndDumpState(void *pArgs)
|
||||
filename.c_str()).c_str(), 2000);
|
||||
|
||||
state_op_in_progress = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SaveStateCallback(u64 userdata, int cyclesLate)
|
||||
@ -263,7 +261,7 @@ void SaveStateCallback(u64 userdata, int cyclesLate)
|
||||
|
||||
Core::DisplayMessage("Saving State...", 1000);
|
||||
|
||||
saveThread = new Common::Thread(CompressAndDumpState, saveData);
|
||||
saveThread = std::thread(CompressAndDumpState, saveData);
|
||||
|
||||
// Resume the clock
|
||||
PowerPC::Start();
|
||||
@ -592,10 +590,9 @@ void State_VerifyBuffer(u8 **buffer)
|
||||
void State_Flush()
|
||||
{
|
||||
// If already saving state, wait for it to finish
|
||||
if (saveThread)
|
||||
if (saveThread.joinable())
|
||||
{
|
||||
delete saveThread;
|
||||
saveThread = NULL;
|
||||
saveThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user