diff --git a/ananke/nall/thread.hpp b/ananke/nall/thread.hpp index 8517726b6..3368d15d2 100644 --- a/ananke/nall/thread.hpp +++ b/ananke/nall/thread.hpp @@ -6,38 +6,79 @@ #include #if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) + #include -//TDM/GCC 4.7 does not support std::thread -//implement an extremely lightweight wrapper - -namespace std { - inline DWORD WINAPI thread_entry_point(LPVOID parameter); +namespace nall { + void* thread_entry_point(void*); struct thread { - bool joinable() const { - return active == false; + thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { + pthread_create(&pthread, NULL, thread_entry_point, (void*)this); + } + + ~thread() { + join(); + } + + bool active() const { + return completed == false; } void join() { - while(active) usleep(1); - } - - thread(function entryPoint) : entryPoint(entryPoint), active(true) { - CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); + if(dead) return; + dead = true; + pthread_join(pthread, NULL); } private: + pthread_t pthread; function entryPoint; - bool active; + volatile bool completed, dead; + friend void* thread_entry_point(void*); + }; + + void* thread_entry_point(void *parameter) { + thread *context = (thread*)parameter; + context->entryPoint(); + context->completed = true; + pthread_exit(0); + } +} +#elif defined(PLATFORM_WIN) +namespace nall { + inline DWORD WINAPI thread_entry_point(LPVOID); + + struct thread { + thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { + hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); + } + + ~thread() { + join(); + } + + bool active() const { + return completed == false; + } + + void join() { + if(dead) return; + dead = true; + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); + } + + private: + HANDLE hthread; + function entryPoint; + volatile bool completed, dead; friend DWORD WINAPI thread_entry_point(LPVOID); }; inline DWORD WINAPI thread_entry_point(LPVOID parameter) { thread *context = (thread*)parameter; context->entryPoint(); - context->active = false; + context->completed = true; return 0; } } diff --git a/ananke/super-famicom.cpp b/ananke/super-famicom.cpp index 4446d7afa..e0c8db350 100644 --- a/ananke/super-famicom.cpp +++ b/ananke/super-famicom.cpp @@ -139,6 +139,8 @@ string Ananke::openSuperFamicom(vector &buffer) { } string Ananke::syncSuperFamicom(const string &pathname) { + if(file::exists({pathname, "msu1.rom"})) return ""; //cannot update MSU1 games + vector buffer; auto append = [&](string filename) { diff --git a/purify/Makefile b/purify/Makefile index 8dc232cea..53ba038fd 100644 --- a/purify/Makefile +++ b/purify/Makefile @@ -22,7 +22,7 @@ obj/purify.o: purify.cpp build: $(objects) ifeq ($(platform),x) - $(cpp) $(link) -o purify $(objects) $(phoenixlink) + $(cpp) -pthread $(link) -o purify $(objects) $(phoenixlink) else ifeq ($(platform),win) windres phoenix/windows/phoenix.rc obj/phoenix-resource.o $(cpp) -shared -o phoenix.dll obj/phoenix.o $(phoenixlink) diff --git a/purify/nall/thread.hpp b/purify/nall/thread.hpp index 8517726b6..3368d15d2 100644 --- a/purify/nall/thread.hpp +++ b/purify/nall/thread.hpp @@ -6,38 +6,79 @@ #include #if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) + #include -//TDM/GCC 4.7 does not support std::thread -//implement an extremely lightweight wrapper - -namespace std { - inline DWORD WINAPI thread_entry_point(LPVOID parameter); +namespace nall { + void* thread_entry_point(void*); struct thread { - bool joinable() const { - return active == false; + thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { + pthread_create(&pthread, NULL, thread_entry_point, (void*)this); + } + + ~thread() { + join(); + } + + bool active() const { + return completed == false; } void join() { - while(active) usleep(1); - } - - thread(function entryPoint) : entryPoint(entryPoint), active(true) { - CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); + if(dead) return; + dead = true; + pthread_join(pthread, NULL); } private: + pthread_t pthread; function entryPoint; - bool active; + volatile bool completed, dead; + friend void* thread_entry_point(void*); + }; + + void* thread_entry_point(void *parameter) { + thread *context = (thread*)parameter; + context->entryPoint(); + context->completed = true; + pthread_exit(0); + } +} +#elif defined(PLATFORM_WIN) +namespace nall { + inline DWORD WINAPI thread_entry_point(LPVOID); + + struct thread { + thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { + hthread = CreateThread(NULL, 0, thread_entry_point, (void*)this, 0, NULL); + } + + ~thread() { + join(); + } + + bool active() const { + return completed == false; + } + + void join() { + if(dead) return; + dead = true; + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); + } + + private: + HANDLE hthread; + function entryPoint; + volatile bool completed, dead; friend DWORD WINAPI thread_entry_point(LPVOID); }; inline DWORD WINAPI thread_entry_point(LPVOID parameter) { thread *context = (thread*)parameter; context->entryPoint(); - context->active = false; + context->completed = true; return 0; } } diff --git a/purify/purify.cpp b/purify/purify.cpp index 1140524bc..18c9f5199 100644 --- a/purify/purify.cpp +++ b/purify/purify.cpp @@ -42,7 +42,7 @@ Application::Application() { } setFrameGeometry({64, 64, 720, 480}); - setTitle("purify v02.01"); + setTitle("purify v03"); layout.setMargin(5); pathLabel.setText("Path:"); @@ -181,8 +181,8 @@ void Application::purify() { OS::processEvents(); PurifyContext purifyContext(purifyList); - std::thread purifyThread([&] { purifyContext.run(); }); - while(purifyContext.position < purifyContext.size) { + nall::thread purifyThread([&] { purifyContext.run(); }); + while(purifyThread.active()) { OS::processEvents(); unsigned position = ((unsigned)(double)purifyContext.position / (double)purifyContext.size * 100.0 + 0.5); progressBar.setPosition(position);