From b08812569cf96dcd5a62c8d0467bd14f3ae90e54 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Mon, 26 Nov 2012 10:34:17 +0000 Subject: [PATCH] Stop using persistent connections when we don't need them. Force shutdown of Thumbnailbroker before http lib close, fixes #84 --- src/client/Client.cpp | 5 +- src/client/ThumbnailBroker.cpp | 90 +++++++++++++++++++++++++--------- src/client/ThumbnailBroker.h | 3 ++ 3 files changed, 73 insertions(+), 25 deletions(-) diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 67a018bbb..fb14050cf 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -140,7 +140,7 @@ void Client::Initialise(std::string proxyString) stampsLib.close(); //Begin version check - versionCheckRequest = http_async_req_start(NULL, SERVER "/Startup.json", NULL, 0, 1); + versionCheckRequest = http_async_req_start(NULL, SERVER "/Startup.json", NULL, 0, 0); if(authUser.ID) { @@ -720,6 +720,7 @@ void Client::WritePrefs() void Client::Shutdown() { + ThumbnailBroker::Ref().Shutdown(); ClearThumbnailRequests(); http_done(); @@ -1827,7 +1828,7 @@ Thumbnail * Client::GetThumbnail(int saveID, int saveDate) { if(!activeThumbRequests[i]) { - activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 1); + activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 0); activeThumbRequestTimes[i] = currentTime; activeThumbRequestCompleteTimes[i] = 0; activeThumbRequestIDs[i] = idString; diff --git a/src/client/ThumbnailBroker.cpp b/src/client/ThumbnailBroker.cpp index e884a980b..92ccfd86b 100644 --- a/src/client/ThumbnailBroker.cpp +++ b/src/client/ThumbnailBroker.cpp @@ -19,6 +19,9 @@ ThumbnailBroker::ThumbnailBroker() //listenersMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_init (&listenersMutex, NULL); + + + pthread_mutex_init (&runningMutex, NULL); } ThumbnailBroker::~ThumbnailBroker() @@ -26,6 +29,45 @@ ThumbnailBroker::~ThumbnailBroker() } +void ThumbnailBroker::assureRunning() +{ + pthread_mutex_lock(&runningMutex); + bool running = thumbnailQueueRunning; + thumbnailQueueRunning = true; + pthread_mutex_unlock(&runningMutex); + + if(!running) + { +#ifdef DEBUG + std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl; +#endif + pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this); + } +} + +void ThumbnailBroker::Shutdown() +{ + pthread_mutex_lock(&runningMutex); + if(thumbnailQueueRunning) + { + thumbnailQueueRunning = false; + pthread_mutex_unlock(&runningMutex); + pthread_join(thumbnailQueueThread, NULL); + } + else + pthread_mutex_unlock(&runningMutex); + + + for (std::list::iterator iter = currentRequests.begin(), end = currentRequests.end(); iter != end; ++iter) + { + ThumbnailRequest req = *iter; + if(req.HTTPContext) + { + http_async_req_close(req.HTTPContext); + } + } +} + void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, int width, int height, ThumbnailListener * tListener) { RenderThumbnail(gameSave, true, true, width, height, tListener); @@ -35,36 +77,20 @@ void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, bool decorations, boo { AttachThumbnailListener(tListener); pthread_mutex_lock(&thumbnailQueueMutex); - bool running = thumbnailQueueRunning; - thumbnailQueueRunning = true; renderRequests.push_back(ThumbRenderRequest(new GameSave(*gameSave), decorations, fire, width, height, ListenerHandle(tListener->ListenerRand, tListener))); pthread_mutex_unlock(&thumbnailQueueMutex); - if(!running) - { -#ifdef DEBUG - std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl; -#endif - pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this); - } + assureRunning(); } void ThumbnailBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener) { AttachThumbnailListener(tListener); pthread_mutex_lock(&thumbnailQueueMutex); - bool running = thumbnailQueueRunning; - thumbnailQueueRunning = true; thumbnailRequests.push_back(ThumbnailRequest(saveID, saveDate, width, height, ListenerHandle(tListener->ListenerRand, tListener))); pthread_mutex_unlock(&thumbnailQueueMutex); - if(!running) - { -#ifdef DEBUG - std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl; -#endif - pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this); - } + assureRunning(); } void * ThumbnailBroker::thumbnailQueueProcessHelper(void * ref) @@ -97,17 +123,33 @@ void ThumbnailBroker::FlushThumbQueue() void ThumbnailBroker::thumbnailQueueProcessTH() { time_t lastAction = time(NULL); + pthread_mutex_lock(&runningMutex); + thumbnailQueueRunning = true; + pthread_mutex_unlock(&runningMutex); while(true) { //Shutdown after 2 seconds of idle if(time(NULL) - lastAction > 2) { - pthread_mutex_lock(&thumbnailQueueMutex); - thumbnailQueueRunning = false; - pthread_mutex_unlock(&thumbnailQueueMutex); +#ifdef DEBUG + std::cout << typeid(*this).name() << " Idle shutdown" << std::endl; +#endif break; } + + pthread_mutex_lock(&runningMutex); + bool running = thumbnailQueueRunning; + pthread_mutex_unlock(&runningMutex); + if(!running) + { +#ifdef DEBUG + std::cout << typeid(*this).name() << " Requested shutdown" << std::endl; +#endif + break; + } + + //Renderer pthread_mutex_lock(&thumbnailQueueMutex); if(renderRequests.size()) @@ -220,7 +262,7 @@ void ThumbnailBroker::thumbnailQueueProcessTH() std::cout << typeid(*this).name() << " Creating new request for " << req.ID.SaveID << ":" << req.ID.SaveDate << std::endl; #endif - req.HTTPContext = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 1); + req.HTTPContext = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 0); req.RequestTime = time(NULL); currentRequests.push_back(req); } @@ -252,7 +294,6 @@ void ThumbnailBroker::thumbnailQueueProcessTH() char * data; int status, data_size, imgw, imgh; data = http_async_req_stop(req.HTTPContext, &status, &data_size); - free(req.HTTPContext); if (status == 200 && data) { @@ -307,6 +348,9 @@ void ThumbnailBroker::thumbnailQueueProcessTH() } } + pthread_mutex_lock(&runningMutex); + thumbnailQueueRunning = false; + pthread_mutex_unlock(&runningMutex); } void ThumbnailBroker::RetrieveThumbnail(int saveID, int width, int height, ThumbnailListener * tListener) diff --git a/src/client/ThumbnailBroker.h b/src/client/ThumbnailBroker.h index ba6d3ae58..516047980 100644 --- a/src/client/ThumbnailBroker.h +++ b/src/client/ThumbnailBroker.h @@ -77,6 +77,7 @@ private: pthread_mutex_t thumbnailQueueMutex; pthread_mutex_t listenersMutex; + pthread_mutex_t runningMutex; pthread_t thumbnailQueueThread; bool thumbnailQueueRunning; std::deque thumbnailRequests; @@ -91,10 +92,12 @@ private: static void * thumbnailQueueProcessHelper(void * ref); void thumbnailQueueProcessTH(); + void assureRunning(); public: ThumbnailBroker(); virtual ~ThumbnailBroker(); + void Shutdown(); void FlushThumbQueue(); void RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener);