From 2e76b10619f9ead5e2a7ce165186a624415e4f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20B=C3=A1lint=20Misius?= Date: Wed, 17 Apr 2019 00:23:57 +0200 Subject: [PATCH] Use C++11 threads --- src/client/http/Request.cpp | 60 +++++------- src/client/http/Request.h | 8 +- src/client/http/RequestManager.cpp | 149 +++++++++++++++-------------- src/client/http/RequestManager.h | 13 ++- src/common/String.cpp | 26 +---- src/common/tpt-thread.h | 26 ----- src/graphics/Graphics.h | 3 - src/graphics/OpenGLGraphics.cpp | 20 ---- src/graphics/RasterGraphics.cpp | 10 -- src/gui/interface/Engine.cpp | 2 - src/gui/search/SearchModel.cpp | 42 ++++---- src/gui/search/SearchModel.h | 32 +++---- src/simulation/Gravity.cpp | 52 +++++----- src/simulation/Gravity.h | 33 ++----- src/simulation/SaveRenderer.cpp | 15 +-- src/simulation/SaveRenderer.h | 4 +- src/tasks/AbandonableTask.cpp | 49 +++++----- src/tasks/AbandonableTask.h | 4 +- src/tasks/Task.cpp | 46 ++++----- src/tasks/Task.h | 11 +-- 20 files changed, 230 insertions(+), 375 deletions(-) delete mode 100644 src/common/tpt-thread.h diff --git a/src/client/http/Request.cpp b/src/client/http/Request.cpp index e4afe4b56..e8808f205 100644 --- a/src/client/http/Request.cpp +++ b/src/client/http/Request.cpp @@ -21,8 +21,6 @@ namespace http post_fields_last(NULL) #endif { - pthread_cond_init(&done_cv, NULL); - pthread_mutex_init(&rm_mutex, NULL); easy = curl_easy_init(); RequestManager::Ref().AddRequest(this); } @@ -36,8 +34,6 @@ namespace http curl_formfree(post_fields_first); #endif curl_slist_free_all(headers); - pthread_mutex_destroy(&rm_mutex); - pthread_cond_destroy(&done_cv); } void Request::AddHeader(ByteString name, ByteString value) @@ -179,9 +175,10 @@ namespace http curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, Request::WriteDataHandler); } - pthread_mutex_lock(&rm_mutex); - rm_started = true; - pthread_mutex_unlock(&rm_mutex); + { + std::lock_guard g(rm_mutex); + rm_started = true; + } RequestManager::Ref().StartRequest(this); } @@ -194,19 +191,18 @@ namespace http return ""; // shouldn't happen but just in case } - pthread_mutex_lock(&rm_mutex); - while (!rm_finished) + ByteString response_out; { - pthread_cond_wait(&done_cv, &rm_mutex); + std::unique_lock l(rm_mutex); + done_cv.wait(l, [this]() { return rm_finished; }); + rm_started = false; + rm_canceled = true; + if (status_out) + { + *status_out = status; + } + response_out = std::move(response_body); } - rm_started = false; - rm_canceled = true; - if (status_out) - { - *status_out = status; - } - ByteString response_out = std::move(response_body); - pthread_mutex_unlock(&rm_mutex); RequestManager::Ref().RemoveRequest(this); return response_out; @@ -214,7 +210,7 @@ namespace http void Request::CheckProgress(int *total, int *done) { - pthread_mutex_lock(&rm_mutex); + std::lock_guard g(rm_mutex); if (total) { *total = rm_total; @@ -223,43 +219,37 @@ namespace http { *done = rm_done; } - pthread_mutex_unlock(&rm_mutex); } // returns true if the request has finished bool Request::CheckDone() { - pthread_mutex_lock(&rm_mutex); - bool ret = rm_finished; - pthread_mutex_unlock(&rm_mutex); - return ret; + std::lock_guard g(rm_mutex); + return rm_finished; } // returns true if the request was canceled bool Request::CheckCanceled() { - pthread_mutex_lock(&rm_mutex); - bool ret = rm_canceled; - pthread_mutex_unlock(&rm_mutex); - return ret; + std::lock_guard g(rm_mutex); + return rm_canceled; } // returns true if the request is running bool Request::CheckStarted() { - pthread_mutex_lock(&rm_mutex); - bool ret = rm_started; - pthread_mutex_unlock(&rm_mutex); - return ret; + std::lock_guard g(rm_mutex); + return rm_started; } // cancels the request, the request thread will delete the Request* when it finishes (do not use Request in any way after canceling) void Request::Cancel() { - pthread_mutex_lock(&rm_mutex); - rm_canceled = true; - pthread_mutex_unlock(&rm_mutex); + { + std::lock_guard g(rm_mutex); + rm_canceled = true; + } RequestManager::Ref().RemoveRequest(this); } diff --git a/src/client/http/Request.h b/src/client/http/Request.h index fe8478518..e72f31b11 100644 --- a/src/client/http/Request.h +++ b/src/client/http/Request.h @@ -3,10 +3,10 @@ #include #include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max -#include "common/tpt-thread.h" +#include +#include #include #include "common/String.h" -#undef GetUserName // pthreads defines this, breaks stuff #if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 55, 0) # define REQUEST_USE_CURL_OFFSET_T @@ -32,7 +32,7 @@ namespace http volatile bool rm_finished; volatile bool rm_canceled; volatile bool rm_started; - pthread_mutex_t rm_mutex; + std::mutex rm_mutex; bool added_to_multi; int status; @@ -46,7 +46,7 @@ namespace http std::map post_fields_map; #endif - pthread_cond_t done_cv; + std::condition_variable done_cv; static size_t WriteDataHandler(char * ptr, size_t size, size_t count, void * userdata); diff --git a/src/client/http/RequestManager.cpp b/src/client/http/RequestManager.cpp index 00295b4a4..068ed9f70 100644 --- a/src/client/http/RequestManager.cpp +++ b/src/client/http/RequestManager.cpp @@ -21,36 +21,27 @@ namespace http rt_shutting_down(false), multi(NULL) { - pthread_cond_init(&rt_cv, NULL); - pthread_mutex_init(&rt_mutex, NULL); } RequestManager::~RequestManager() { - pthread_mutex_destroy(&rt_mutex); - pthread_cond_destroy(&rt_cv); } void RequestManager::Shutdown() { - pthread_mutex_lock(&rt_mutex); - rt_shutting_down = true; - pthread_cond_signal(&rt_cv); - pthread_mutex_unlock(&rt_mutex); + { + std::lock_guard g(rt_mutex); + rt_shutting_down = true; + } + rt_cv.notify_one(); - pthread_join(worker_thread, NULL); + worker_thread.join(); curl_multi_cleanup(multi); multi = NULL; curl_global_cleanup(); } - TH_ENTRY_POINT void *RequestManager::RequestManagerHelper(void *obj) - { - ((RequestManager *)obj)->Worker(); - return NULL; - } - void RequestManager::Initialise(ByteString Proxy) { curl_global_init(CURL_GLOBAL_DEFAULT); @@ -64,7 +55,7 @@ namespace http user_agent = ByteString::Build("PowderToy/", SAVE_VERSION, ".", MINOR_VERSION, " (", IDENT_PLATFORM, "; ", IDENT_BUILD, "; M", MOD_ID, ") TPTPP/", SAVE_VERSION, ".", MINOR_VERSION, ".", BUILD_NUM, IDENT_RELTYPE, ".", SNAPSHOT_ID); - pthread_create(&worker_thread, NULL, &RequestManager::RequestManagerHelper, this); + worker_thread = std::thread([this]() { Worker(); }); } void RequestManager::Worker() @@ -72,24 +63,25 @@ namespace http bool shutting_down = false; while (!shutting_down) { - pthread_mutex_lock(&rt_mutex); - if (!requests_added_to_multi) { - while (!rt_shutting_down && requests_to_add.empty() && !requests_to_start && !requests_to_remove) + std::unique_lock l(rt_mutex); + if (!requests_added_to_multi) { - pthread_cond_wait(&rt_cv, &rt_mutex); + while (!rt_shutting_down && requests_to_add.empty() && !requests_to_start && !requests_to_remove) + { + rt_cv.wait(l); + } } + shutting_down = rt_shutting_down; + requests_to_remove = false; + requests_to_start = false; + for (Request *request : requests_to_add) + { + request->status = 0; + requests.insert(request); + } + requests_to_add.clear(); } - shutting_down = rt_shutting_down; - requests_to_remove = false; - requests_to_start = false; - for (Request *request : requests_to_add) - { - request->status = 0; - requests.insert(request); - } - requests_to_add.clear(); - pthread_mutex_unlock(&rt_mutex); if (multi && requests_added_to_multi) { @@ -157,52 +149,60 @@ namespace http std::set requests_to_remove; for (Request *request : requests) { - pthread_mutex_lock(&request->rm_mutex); - if (shutting_down) + bool signal_done = false; + { - // In the weird case that a http::Request::Simple* call is - // waiting on this Request, we should fail the request - // instead of cancelling it ourselves. - request->status = 610; - } - if (!request->rm_canceled && request->rm_started && !request->added_to_multi && !request->status) - { - if (multi && request->easy) + std::lock_guard g(request->rm_mutex); + if (shutting_down) { - MultiAdd(request); + // In the weird case that a http::Request::Simple* call is + // waiting on this Request, we should fail the request + // instead of cancelling it ourselves. + request->status = 610; } - else + if (!request->rm_canceled && request->rm_started && !request->added_to_multi && !request->status) { - request->status = 604; + if (multi && request->easy) + { + MultiAdd(request); + } + else + { + request->status = 604; + } } - } - if (!request->rm_canceled && request->rm_started && !request->rm_finished) - { - if (multi && request->easy) + if (!request->rm_canceled && request->rm_started && !request->rm_finished) { + if (multi && request->easy) + { #ifdef REQUEST_USE_CURL_OFFSET_T - curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &request->rm_total); - curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD_T, &request->rm_done); + curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &request->rm_total); + curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD_T, &request->rm_done); #else - double total, done; - curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &total); - curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD, &done); - request->rm_total = (curl_off_t)total; - request->rm_done = (curl_off_t)done; + double total, done; + curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &total); + curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD, &done); + request->rm_total = (curl_off_t)total; + request->rm_done = (curl_off_t)done; #endif + } + if (request->status) + { + request->rm_finished = true; + MultiRemove(request); + signal_done = true; + } } - if (request->status) + if (request->rm_canceled) { - request->rm_finished = true; - MultiRemove(request); - pthread_cond_signal(&request->done_cv); + requests_to_remove.insert(request); } } - if (request->rm_canceled) + + if (signal_done) { - requests_to_remove.insert(request); + request->done_cv.notify_one(); } - pthread_mutex_unlock(&request->rm_mutex); } for (Request *request : requests_to_remove) { @@ -235,25 +235,28 @@ namespace http void RequestManager::AddRequest(Request *request) { - pthread_mutex_lock(&rt_mutex); - requests_to_add.insert(request); - pthread_cond_signal(&rt_cv); - pthread_mutex_unlock(&rt_mutex); + { + std::lock_guard g(rt_mutex); + requests_to_add.insert(request); + } + rt_cv.notify_one(); } void RequestManager::StartRequest(Request *request) { - pthread_mutex_lock(&rt_mutex); - requests_to_start = true; - pthread_cond_signal(&rt_cv); - pthread_mutex_unlock(&rt_mutex); + { + std::lock_guard g(rt_mutex); + requests_to_start = true; + } + rt_cv.notify_one(); } void RequestManager::RemoveRequest(Request *request) { - pthread_mutex_lock(&rt_mutex); - requests_to_remove = true; - pthread_cond_signal(&rt_cv); - pthread_mutex_unlock(&rt_mutex); + { + std::lock_guard g(rt_mutex); + requests_to_remove = true; + } + rt_cv.notify_one(); } } diff --git a/src/client/http/RequestManager.h b/src/client/http/RequestManager.h index 222778243..19e1e2df3 100644 --- a/src/client/http/RequestManager.h +++ b/src/client/http/RequestManager.h @@ -2,20 +2,21 @@ #define REQUESTMANAGER_H #include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max -#include "common/tpt-thread.h" +#include +#include +#include #include #include #include #include "common/Singleton.h" #include "common/String.h" -#undef GetUserName // pthreads (included by curl) defines this, breaks stuff namespace http { class Request; class RequestManager : public Singleton { - pthread_t worker_thread; + std::thread worker_thread; std::set requests; int requests_added_to_multi; @@ -23,8 +24,8 @@ namespace http bool requests_to_start; bool requests_to_remove; bool rt_shutting_down; - pthread_mutex_t rt_mutex; - pthread_cond_t rt_cv; + std::mutex rt_mutex; + std::condition_variable rt_cv; CURLM *multi; @@ -36,8 +37,6 @@ namespace http void StartRequest(Request *request); void RemoveRequest(Request *request); - static TH_ENTRY_POINT void *RequestManagerHelper(void *obj); - public: RequestManager(); ~RequestManager(); diff --git a/src/common/String.cpp b/src/common/String.cpp index df56d5ec8..6bd593b5b 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -4,7 +4,6 @@ #include #include -#include "common/tpt-thread.h" #include "String.h" ByteString ConversionError::formatError(ByteString::value_type const *at, ByteString::value_type const *upto) @@ -374,31 +373,10 @@ struct LocaleImpl } }; -static void destroyLocaleImpl(void *ptr) -{ - delete static_cast(ptr); -} - -static pthread_once_t localeOnce = PTHREAD_ONCE_INIT; -static pthread_key_t localeKey; - -static void createLocaleKey() -{ - if(int error = pthread_key_create(&localeKey, destroyLocaleImpl)) - throw std::system_error(error, std::system_category(), "Could not create TLS key for LocaleImpl"); -} - static LocaleImpl *getLocaleImpl() { - pthread_once(&localeOnce, createLocaleKey); - void *ptr = pthread_getspecific(localeKey); - if(!ptr) - { - ptr = static_cast(new LocaleImpl()); - if(int error = pthread_setspecific(localeKey, ptr)) - throw std::system_error(error, std::system_category(), "Could not put LocaleImpl into TLS"); - } - return static_cast(ptr); + thread_local LocaleImpl li; + return &li; } ByteString ByteStringBuilder::Build() const diff --git a/src/common/tpt-thread.h b/src/common/tpt-thread.h deleted file mode 100644 index 276ddd070..000000000 --- a/src/common/tpt-thread.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TPT_THREAD_H -#define TPT_THREAD_H - -#if defined(WIN) && defined(__GNUC__) -#define TH_ENTRY_POINT __attribute__((force_align_arg_pointer)) -#define _TIMESPEC_DEFINED -#else -#define TH_ENTRY_POINT -#endif - -// fix 'timespec' error in VS 2015 -#if defined(_MSC_VER) && (_MSC_VER >= 1900) -#define _TIMESPEC_DEFINED 1 -#endif - -#include -#undef GetUserName - -// Fix deprecation warnings with recent pthread versions on Windows -#if defined(_PTW32_STATIC_LIB) && defined(WIN) -#if PTW32_VERSION <= 2, 8, 0, 0 -#define PTW32_STATIC_LIB -#endif -#endif - -#endif diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index 5d0ab4850..5bfb8216c 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -128,9 +128,6 @@ public: VideoBuffer DumpFrame(); - void Acquire(); - void Release(); - void blendpixel(int x, int y, int r, int g, int b, int a); void addpixel(int x, int y, int r, int g, int b, int a); diff --git a/src/graphics/OpenGLGraphics.cpp b/src/graphics/OpenGLGraphics.cpp index 7aa1785e4..a42c4c903 100644 --- a/src/graphics/OpenGLGraphics.cpp +++ b/src/graphics/OpenGLGraphics.cpp @@ -1,22 +1,12 @@ #include "Graphics.h" #include "FontReader.h" -#include "common/tpt-thread.h" #ifdef OGLI -static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER; -//static pthread_mutex_t TMPMUT = PTHREAD_MUTEX_INITIALIZER; Graphics::Graphics(): sdl_scale(1) { -// if(gMutex == TMPMUT) -// pthread_mutex_init (&gMutex, NULL); LoadDefaults(); InitialiseTextures(); - - - - //Texture for main UI - } void Graphics::LoadDefaults() @@ -68,16 +58,6 @@ void Graphics::DestroyTextures() //Todo... } -void Graphics::Acquire() -{ - pthread_mutex_lock(&gMutex); -} - -void Graphics::Release() -{ - pthread_mutex_unlock(&gMutex); -} - Graphics::~Graphics() { } diff --git a/src/graphics/RasterGraphics.cpp b/src/graphics/RasterGraphics.cpp index a2dbf3904..8b0e00f12 100644 --- a/src/graphics/RasterGraphics.cpp +++ b/src/graphics/RasterGraphics.cpp @@ -9,16 +9,6 @@ sdl_scale(1) } -void Graphics::Acquire() -{ - -} - -void Graphics::Release() -{ - -} - Graphics::~Graphics() { free(vid); diff --git a/src/gui/interface/Engine.cpp b/src/gui/interface/Engine.cpp index 56cafe339..7a5c768a1 100644 --- a/src/gui/interface/Engine.cpp +++ b/src/gui/interface/Engine.cpp @@ -225,7 +225,6 @@ void Engine::Draw() { if(lastBuffer && !(state_ && state_->Position.X == 0 && state_->Position.Y == 0 && state_->Size.X == width_ && state_->Size.Y == height_)) { - g->Acquire(); g->Clear(); #ifndef OGLI memcpy(g->vid, lastBuffer, (width_ * height_) * PIXELSIZE); @@ -242,7 +241,6 @@ void Engine::Draw() state_->DoDraw(); g->Finalise(); - g->Release(); FrameIndex++; FrameIndex %= 7200; } diff --git a/src/gui/search/SearchModel.cpp b/src/gui/search/SearchModel.cpp index 436112e3f..de8caf111 100644 --- a/src/gui/search/SearchModel.cpp +++ b/src/gui/search/SearchModel.cpp @@ -3,6 +3,8 @@ #include "client/Client.h" +#include + SearchModel::SearchModel(): loadedSave(NULL), currentSort("best"), @@ -14,8 +16,10 @@ SearchModel::SearchModel(): saveListLoaded(false), updateSaveListWorking(false), updateSaveListFinished(false), + updateSaveListResult(nullptr), updateTagListWorking(false), - updateTagListFinished(false) + updateTagListFinished(false), + updateTagListResult(nullptr) { } @@ -29,36 +33,26 @@ bool SearchModel::GetShowTags() return showTags; } -TH_ENTRY_POINT void * SearchModel::updateSaveListTHelper(void * obj) -{ - return ((SearchModel *)obj)->updateSaveListT(); -} - -void * SearchModel::updateSaveListT() +void SearchModel::updateSaveListT() { ByteString category = ""; if(showFavourite) category = "Favourites"; if(showOwn && Client::Ref().GetAuthUser().UserID) category = "by:"+Client::Ref().GetAuthUser().Username; - vector * saveList = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, thResultCount); + std::vector * saveList = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, thResultCount); + updateSaveListResult = saveList; updateSaveListFinished = true; - return saveList; } -TH_ENTRY_POINT void * SearchModel::updateTagListTHelper(void * obj) -{ - return ((SearchModel *)obj)->updateTagListT(); -} - -void * SearchModel::updateTagListT() +void SearchModel::updateTagListT() { int tagResultCount; std::vector > * tagList = Client::Ref().GetTags(0, 24, "", tagResultCount); + updateTagListResult = tagList; updateTagListFinished = true; - return tagList; } bool SearchModel::UpdateSaveList(int pageNumber, String query) @@ -88,12 +82,12 @@ bool SearchModel::UpdateSaveList(int pageNumber, String query) { updateTagListFinished = false; updateTagListWorking = true; - pthread_create(&updateTagListThread, 0, &SearchModel::updateTagListTHelper, this); + std::thread([this]() { updateTagListT(); }).detach(); } updateSaveListFinished = false; updateSaveListWorking = true; - pthread_create(&updateSaveListThread, 0, &SearchModel::updateSaveListTHelper, this); + std::thread([this]() { updateSaveListT(); }).detach(); return true; } return false; @@ -117,12 +111,12 @@ SaveInfo * SearchModel::GetLoadedSave(){ return loadedSave; } -vector SearchModel::GetSaveList() +std::vector SearchModel::GetSaveList() { return saveList; } -vector > SearchModel::GetTagList() +std::vector > SearchModel::GetTagList() { return tagList; } @@ -137,8 +131,8 @@ void SearchModel::Update() lastError = ""; saveListLoaded = true; - vector * tempSaveList; - pthread_join(updateSaveListThread, (void**)&tempSaveList); + std::vector *tempSaveList = updateSaveListResult; + updateSaveListResult = nullptr; if(tempSaveList) { @@ -164,8 +158,8 @@ void SearchModel::Update() { updateTagListWorking = false; - vector > * tempTagList; - pthread_join(updateTagListThread, (void**)&tempTagList); + std::vector> *tempTagList = updateTagListResult; + updateTagListResult = nullptr; if(tempTagList) { diff --git a/src/gui/search/SearchModel.h b/src/gui/search/SearchModel.h index c1ed5673e..fc62d0c80 100644 --- a/src/gui/search/SearchModel.h +++ b/src/gui/search/SearchModel.h @@ -4,13 +4,11 @@ #include #include "common/String.h" #include "common/tpt-minmax.h" -#include "common/tpt-thread.h" +#include #include #include "client/SaveInfo.h" #include "SearchView.h" -using namespace std; - class SearchView; class SearchModel { @@ -19,10 +17,10 @@ private: ByteString currentSort; String lastQuery; String lastError; - vector selected; - vector observers; - vector saveList; - vector > tagList; + std::vector selected; + std::vector observers; + std::vector saveList; + std::vector > tagList; int currentPage; int resultCount; int thResultCount; @@ -40,16 +38,14 @@ private: //Variables and methods for background save request bool saveListLoaded; bool updateSaveListWorking; - volatile bool updateSaveListFinished; - pthread_t updateSaveListThread; - TH_ENTRY_POINT static void * updateSaveListTHelper(void * obj); - void * updateSaveListT(); + std::atomic updateSaveListFinished; + void updateSaveListT(); + std::vector *updateSaveListResult; bool updateTagListWorking; - volatile bool updateTagListFinished; - pthread_t updateTagListThread; - TH_ENTRY_POINT static void * updateTagListTHelper(void * obj); - void * updateTagListT(); + std::atomic updateTagListFinished; + void updateTagListT(); + std::vector> *updateTagListResult; public: SearchModel(); virtual ~SearchModel(); @@ -58,8 +54,8 @@ public: bool GetShowTags(); void AddObserver(SearchView * observer); bool UpdateSaveList(int pageNumber, String query); - vector GetSaveList(); - vector > GetTagList(); + std::vector GetSaveList(); + std::vector > GetTagList(); String GetLastError() { return lastError; } int GetPageCount() { @@ -79,7 +75,7 @@ public: void SetLoadedSave(SaveInfo * save); SaveInfo * GetLoadedSave(); bool GetSavesLoaded() { return saveListLoaded; } - vector GetSelected() { return selected; } + std::vector GetSelected() { return selected; } void ClearSelected() { selected.clear(); notifySelectedChanged(); } void SelectSave(int saveID); void DeselectSave(int saveID); diff --git a/src/simulation/Gravity.cpp b/src/simulation/Gravity.cpp index 9ec91dba7..ac4ce6f05 100755 --- a/src/simulation/Gravity.cpp +++ b/src/simulation/Gravity.cpp @@ -1,6 +1,5 @@ #include #include -#include "common/tpt-thread.h" #include "Config.h" #include "Gravity.h" #include "Misc.h" @@ -85,13 +84,15 @@ void Gravity::gravity_update_async() int result; if (ngrav_enable) { - if (!pthread_mutex_trylock(&gravmutex)) + bool signal_grav = false; + { - result = grav_ready; - if (result) //Did the gravity thread finish? + std::unique_lock l(gravmutex, std::defer_lock); + if (l.try_lock()) { - //if (!sys_pause||framerender){ //Only update if not paused - //Switch the full size gravmaps, we don't really need the two above any more + result = grav_ready; + if (result) //Did the gravity thread finish? + { float *tmpf; if (th_gravchanged && !ignoreNextResult) @@ -121,10 +122,14 @@ void Gravity::gravity_update_async() th_gravmap = tmpf; grav_ready = 0; //Tell the other thread that we're ready for it to continue - pthread_cond_signal(&gravcv); - //} + signal_grav = true; + } + } + + if (signal_grav) + { + gravcv.notify_one(); } - pthread_mutex_unlock(&gravmutex); } //Apply the gravity mask membwand(gravy, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); @@ -133,12 +138,6 @@ void Gravity::gravity_update_async() } } -TH_ENTRY_POINT void *Gravity::update_grav_async_helper(void * context) -{ - ((Gravity *)context)->update_grav_async(); - return NULL; -} - void Gravity::update_grav_async() { int done = 0; @@ -155,7 +154,8 @@ void Gravity::update_grav_async() if (!grav_fft_status) grav_fft_init(); #endif - pthread_mutex_lock(&gravmutex); + + std::unique_lock l(gravmutex); while (!thread_done) { if (!done) @@ -167,13 +167,11 @@ void Gravity::update_grav_async() thread_done = gravthread_done; } else { // wait for main thread - pthread_cond_wait(&gravcv, &gravmutex); + gravcv.wait(l); done = grav_ready; thread_done = gravthread_done; } } - pthread_mutex_unlock(&gravmutex); - pthread_exit(NULL); } void Gravity::start_grav_async() @@ -183,9 +181,7 @@ void Gravity::start_grav_async() gravthread_done = 0; grav_ready = 0; - pthread_mutex_init (&gravmutex, NULL); - pthread_cond_init(&gravcv, NULL); - pthread_create(&gravthread, NULL, &Gravity::update_grav_async_helper, this); //Start asynchronous gravity simulation + gravthread = std::thread([this]() { update_grav_async(); }); //Start asynchronous gravity simulation ngrav_enable = 1; memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); @@ -198,12 +194,12 @@ void Gravity::stop_grav_async() { if (ngrav_enable) { - pthread_mutex_lock(&gravmutex); - gravthread_done = 1; - pthread_cond_signal(&gravcv); - pthread_mutex_unlock(&gravmutex); - pthread_join(gravthread, NULL); - pthread_mutex_destroy(&gravmutex); //Destroy the mutex + { + std::lock_guard g(gravmutex); + gravthread_done = 1; + } + gravcv.notify_one(); + gravthread.join(); ngrav_enable = 0; } //Clear the grav velocities diff --git a/src/simulation/Gravity.h b/src/simulation/Gravity.h index 6cc612a33..54ba20357 100644 --- a/src/simulation/Gravity.h +++ b/src/simulation/Gravity.h @@ -1,7 +1,9 @@ #ifndef GRAVITY_H #define GRAVITY_H -#include "common/tpt-thread.h" +#include +#include +#include #include "Config.h" #include "Simulation.h" @@ -18,28 +20,6 @@ struct mask_el { }; typedef struct mask_el mask_el; - -/* - * float *gravmap = NULL;//Maps to be used by the main thread - float *gravp = NULL; - float *gravy = NULL; - float *gravx = NULL; - unsigned *gravmask = NULL; - - float *th_ogravmap = NULL;// Maps to be processed by the gravity thread - float *th_gravmap = NULL; - float *th_gravx = NULL; - float *th_gravy = NULL; - float *th_gravp = NULL; - - int th_gravchanged = 0; - - pthread_t gravthread; - pthread_mutex_t gravmutex; - pthread_cond_t gravcv; - int grav_ready = 0; - int gravthread_done = 0; - */ class Gravity { private: @@ -52,9 +32,9 @@ private: int th_gravchanged; - pthread_t gravthread; - pthread_mutex_t gravmutex; - pthread_cond_t gravcv; + std::thread gravthread; + std::mutex gravmutex; + std::condition_variable gravcv; int grav_ready; int gravthread_done; @@ -84,7 +64,6 @@ public: void gravity_cleanup(); void gravity_update_async(); - TH_ENTRY_POINT static void *update_grav_async_helper(void * context); void update_grav_async(); void start_grav_async(); diff --git a/src/simulation/SaveRenderer.cpp b/src/simulation/SaveRenderer.cpp index 67232715a..8b745f8bb 100644 --- a/src/simulation/SaveRenderer.cpp +++ b/src/simulation/SaveRenderer.cpp @@ -29,13 +29,11 @@ SaveRenderer::SaveRenderer(){ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding glDisable(GL_TEXTURE_2D); #endif - - pthread_mutex_init(&renderMutex, NULL); } VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire) { - pthread_mutex_lock(&renderMutex); + std::lock_guard gx(renderMutex); int width, height; VideoBuffer * tempThumb = NULL; @@ -43,7 +41,6 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire) height = save->blockHeight; bool doCollapse = save->Collapsed(); - g->Acquire(); g->Clear(); sim->clear_sim(); @@ -148,15 +145,13 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire) } if(doCollapse) save->Collapse(); - g->Release(); - pthread_mutex_unlock(&renderMutex); return tempThumb; } VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool decorations, bool fire) { - pthread_mutex_lock(&renderMutex); + std::lock_guard g(renderMutex); GameSave * tempSave; try { @@ -167,17 +162,15 @@ VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool VideoBuffer * buffer = new VideoBuffer(64, 64); buffer->BlendCharacter(32, 32, 'x', 255, 255, 255, 255); - pthread_mutex_unlock(&renderMutex); return buffer; } VideoBuffer * thumb = Render(tempSave, decorations, fire); delete tempSave; - pthread_mutex_unlock(&renderMutex); return thumb; } -SaveRenderer::~SaveRenderer() { - pthread_mutex_destroy(&renderMutex); +SaveRenderer::~SaveRenderer() +{ } diff --git a/src/simulation/SaveRenderer.h b/src/simulation/SaveRenderer.h index d1e9cc871..0cb0bf1f4 100644 --- a/src/simulation/SaveRenderer.h +++ b/src/simulation/SaveRenderer.h @@ -4,7 +4,7 @@ #include "graphics/OpenGLHeaders.h" #endif #include "common/Singleton.h" -#include "common/tpt-thread.h" +#include class GameSave; class VideoBuffer; @@ -16,7 +16,7 @@ class SaveRenderer: public Singleton { Graphics * g; Simulation * sim; Renderer * ren; - pthread_mutex_t renderMutex; + std::mutex renderMutex; public: SaveRenderer(); VideoBuffer * Render(GameSave * save, bool decorations = true, bool fire = true); diff --git a/src/tasks/AbandonableTask.cpp b/src/tasks/AbandonableTask.cpp index 2d91703b4..147aa8318 100644 --- a/src/tasks/AbandonableTask.cpp +++ b/src/tasks/AbandonableTask.cpp @@ -5,11 +5,13 @@ void AbandonableTask::doWork_wrapper() { Task::doWork_wrapper(); - pthread_cond_signal(&done_cv); + done_cv.notify_one(); - pthread_mutex_lock(&taskMutex); - bool abandoned = thAbandoned; - pthread_mutex_unlock(&taskMutex); + bool abandoned; + { + std::lock_guard g(taskMutex); + abandoned = thAbandoned; + } if (abandoned) { delete this; @@ -18,12 +20,10 @@ void AbandonableTask::doWork_wrapper() void AbandonableTask::Finish() { - pthread_mutex_lock(&taskMutex); - while (!thDone) { - pthread_cond_wait(&done_cv, &taskMutex); + std::unique_lock l(taskMutex); + done_cv.wait(l, [this]() { return thDone; }); } - pthread_mutex_unlock(&taskMutex); // Poll to make sure that the rest of the Task knows that it's // done, not just us. This has to be done because the thread that started @@ -37,23 +37,24 @@ void AbandonableTask::Finish() void AbandonableTask::Abandon() { bool delete_this = false; - pthread_mutex_lock(&taskMutex); - if (thDone) { - // If thDone is true, the thread has already finished. We're - // not calling Poll because it may call callbacks, which - // an abandoned task shouldn't do. Instead we just delete the - // AbandonableTask after unlocking the mutex. - delete_this = true; + std::lock_guard g(taskMutex); + if (thDone) + { + // If thDone is true, the thread has already finished. We're + // not calling Poll because it may call callbacks, which + // an abandoned task shouldn't do. Instead we just delete the + // AbandonableTask after unlocking the mutex. + delete_this = true; + } + else + { + // If at this point thDone is still false, the thread is still + // running, meaning we can safely set thAbandoned and let + // AbandonableTask::doWork_wrapper delete the AbandonableTask later. + thAbandoned = true; + } } - else - { - // If at this point thDone is still false, the thread is still - // running, meaning we can safely set thAbandoned and let - // AbandonableTask::doWork_wrapper delete the AbandonableTask later. - thAbandoned = true; - } - pthread_mutex_unlock(&taskMutex); if (delete_this) { @@ -64,11 +65,9 @@ void AbandonableTask::Abandon() AbandonableTask::AbandonableTask() : thAbandoned(false) { - pthread_cond_init(&done_cv, NULL); } AbandonableTask::~AbandonableTask() { - pthread_cond_destroy(&done_cv); } diff --git a/src/tasks/AbandonableTask.h b/src/tasks/AbandonableTask.h index 372410c55..afeee9549 100644 --- a/src/tasks/AbandonableTask.h +++ b/src/tasks/AbandonableTask.h @@ -3,9 +3,11 @@ #include "Task.h" +#include + class AbandonableTask : public Task { - pthread_cond_t done_cv; + std::condition_variable done_cv; public: void Finish(); diff --git a/src/tasks/Task.cpp b/src/tasks/Task.cpp index 85d2a72fe..7ed8872d0 100644 --- a/src/tasks/Task.cpp +++ b/src/tasks/Task.cpp @@ -12,10 +12,7 @@ void Task::AddTaskListener(TaskListener * listener) void Task::Start() { before(); - // This would use a lambda if we didn't use pthreads and if I dared omit - // the TH_ENTRY_POINT from the function type. - pthread_create(&doWorkThread, 0, &Task::doWork_helper, this); - pthread_detach(doWorkThread); + std::thread([this]() { doWork_wrapper(); }).detach(); } int Task::GetProgress() @@ -52,13 +49,14 @@ void Task::Poll() bool newSuccess = false; String newStatus; String newError; - pthread_mutex_lock(&taskMutex); - newProgress = thProgress; - newDone = thDone; - newSuccess = thSuccess; - newStatus = thStatus; - newError = thError; - pthread_mutex_unlock(&taskMutex); + { + std::lock_guard g(taskMutex); + newProgress = thProgress; + newDone = thDone; + newSuccess = thSuccess; + newStatus = thStatus; + newError = thError; + } success = newSuccess; @@ -93,12 +91,10 @@ Task::Task() : thDone(false), listener(NULL) { - pthread_mutex_init(&taskMutex, NULL); } Task::~Task() { - pthread_mutex_destroy(&taskMutex); } void Task::before() @@ -124,37 +120,29 @@ void Task::after() void Task::doWork_wrapper() { bool newSuccess = doWork(); - pthread_mutex_lock(&taskMutex); - thSuccess = newSuccess; - thDone = true; - pthread_mutex_unlock(&taskMutex); -} - -TH_ENTRY_POINT void *Task::doWork_helper(void *ref) -{ - ((Task *)ref)->doWork_wrapper(); - return NULL; + { + std::lock_guard g(taskMutex); + thSuccess = newSuccess; + thDone = true; + } } void Task::notifyProgress(int progress) { - pthread_mutex_lock(&taskMutex); + std::lock_guard g(taskMutex); thProgress = progress; - pthread_mutex_unlock(&taskMutex); } void Task::notifyStatus(String status) { - pthread_mutex_lock(&taskMutex); + std::lock_guard g(taskMutex); thStatus = status; - pthread_mutex_unlock(&taskMutex); } void Task::notifyError(String error) { - pthread_mutex_lock(&taskMutex); + std::lock_guard g(taskMutex); thError = error; - pthread_mutex_unlock(&taskMutex); } void Task::notifyProgressMain() diff --git a/src/tasks/Task.h b/src/tasks/Task.h index 4858974c3..4d747abea 100644 --- a/src/tasks/Task.h +++ b/src/tasks/Task.h @@ -2,9 +2,10 @@ #define TASK_H_ #include "common/String.h" -#include "common/tpt-thread.h" #include "TaskListener.h" #include "Config.h" +#include +#include class TaskListener; class Task { @@ -19,6 +20,7 @@ public: virtual void Poll(); Task(); virtual ~Task(); + protected: int progress; bool done; @@ -32,16 +34,13 @@ protected: String thStatus; String thError; - TaskListener * listener; - pthread_t doWorkThread; - pthread_mutex_t taskMutex; - + TaskListener *listener; + std::mutex taskMutex; virtual void before(); virtual void after(); virtual bool doWork(); virtual void doWork_wrapper(); - TH_ENTRY_POINT static void * doWork_helper(void * ref); virtual void notifyProgress(int progress); virtual void notifyError(String error);