Stop using persistent connections when we don't need them. Force shutdown of Thumbnailbroker before http lib close, fixes #84

This commit is contained in:
Simon Robertshaw
2012-11-26 10:34:17 +00:00
parent 6a4040f2b7
commit b08812569c
3 changed files with 73 additions and 25 deletions

View File

@@ -140,7 +140,7 @@ void Client::Initialise(std::string proxyString)
stampsLib.close(); stampsLib.close();
//Begin version check //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) if(authUser.ID)
{ {
@@ -720,6 +720,7 @@ void Client::WritePrefs()
void Client::Shutdown() void Client::Shutdown()
{ {
ThumbnailBroker::Ref().Shutdown();
ClearThumbnailRequests(); ClearThumbnailRequests();
http_done(); http_done();
@@ -1827,7 +1828,7 @@ Thumbnail * Client::GetThumbnail(int saveID, int saveDate)
{ {
if(!activeThumbRequests[i]) 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; activeThumbRequestTimes[i] = currentTime;
activeThumbRequestCompleteTimes[i] = 0; activeThumbRequestCompleteTimes[i] = 0;
activeThumbRequestIDs[i] = idString; activeThumbRequestIDs[i] = idString;

View File

@@ -19,6 +19,9 @@ ThumbnailBroker::ThumbnailBroker()
//listenersMutex = PTHREAD_MUTEX_INITIALIZER; //listenersMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init (&listenersMutex, NULL); pthread_mutex_init (&listenersMutex, NULL);
pthread_mutex_init (&runningMutex, NULL);
} }
ThumbnailBroker::~ThumbnailBroker() 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<ThumbnailRequest>::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) void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, int width, int height, ThumbnailListener * tListener)
{ {
RenderThumbnail(gameSave, true, true, width, height, tListener); RenderThumbnail(gameSave, true, true, width, height, tListener);
@@ -35,36 +77,20 @@ void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, bool decorations, boo
{ {
AttachThumbnailListener(tListener); AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex); pthread_mutex_lock(&thumbnailQueueMutex);
bool running = thumbnailQueueRunning;
thumbnailQueueRunning = true;
renderRequests.push_back(ThumbRenderRequest(new GameSave(*gameSave), decorations, fire, width, height, ListenerHandle(tListener->ListenerRand, tListener))); renderRequests.push_back(ThumbRenderRequest(new GameSave(*gameSave), decorations, fire, width, height, ListenerHandle(tListener->ListenerRand, tListener)));
pthread_mutex_unlock(&thumbnailQueueMutex); pthread_mutex_unlock(&thumbnailQueueMutex);
if(!running) assureRunning();
{
#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::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener) void ThumbnailBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener)
{ {
AttachThumbnailListener(tListener); AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex); pthread_mutex_lock(&thumbnailQueueMutex);
bool running = thumbnailQueueRunning;
thumbnailQueueRunning = true;
thumbnailRequests.push_back(ThumbnailRequest(saveID, saveDate, width, height, ListenerHandle(tListener->ListenerRand, tListener))); thumbnailRequests.push_back(ThumbnailRequest(saveID, saveDate, width, height, ListenerHandle(tListener->ListenerRand, tListener)));
pthread_mutex_unlock(&thumbnailQueueMutex); pthread_mutex_unlock(&thumbnailQueueMutex);
if(!running) assureRunning();
{
#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::thumbnailQueueProcessHelper(void * ref) void * ThumbnailBroker::thumbnailQueueProcessHelper(void * ref)
@@ -97,17 +123,33 @@ void ThumbnailBroker::FlushThumbQueue()
void ThumbnailBroker::thumbnailQueueProcessTH() void ThumbnailBroker::thumbnailQueueProcessTH()
{ {
time_t lastAction = time(NULL); time_t lastAction = time(NULL);
pthread_mutex_lock(&runningMutex);
thumbnailQueueRunning = true;
pthread_mutex_unlock(&runningMutex);
while(true) while(true)
{ {
//Shutdown after 2 seconds of idle //Shutdown after 2 seconds of idle
if(time(NULL) - lastAction > 2) if(time(NULL) - lastAction > 2)
{ {
pthread_mutex_lock(&thumbnailQueueMutex); #ifdef DEBUG
thumbnailQueueRunning = false; std::cout << typeid(*this).name() << " Idle shutdown" << std::endl;
pthread_mutex_unlock(&thumbnailQueueMutex); #endif
break; 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 //Renderer
pthread_mutex_lock(&thumbnailQueueMutex); pthread_mutex_lock(&thumbnailQueueMutex);
if(renderRequests.size()) 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; std::cout << typeid(*this).name() << " Creating new request for " << req.ID.SaveID << ":" << req.ID.SaveDate << std::endl;
#endif #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); req.RequestTime = time(NULL);
currentRequests.push_back(req); currentRequests.push_back(req);
} }
@@ -252,7 +294,6 @@ void ThumbnailBroker::thumbnailQueueProcessTH()
char * data; char * data;
int status, data_size, imgw, imgh; int status, data_size, imgw, imgh;
data = http_async_req_stop(req.HTTPContext, &status, &data_size); data = http_async_req_stop(req.HTTPContext, &status, &data_size);
free(req.HTTPContext);
if (status == 200 && data) 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) void ThumbnailBroker::RetrieveThumbnail(int saveID, int width, int height, ThumbnailListener * tListener)

View File

@@ -77,6 +77,7 @@ private:
pthread_mutex_t thumbnailQueueMutex; pthread_mutex_t thumbnailQueueMutex;
pthread_mutex_t listenersMutex; pthread_mutex_t listenersMutex;
pthread_mutex_t runningMutex;
pthread_t thumbnailQueueThread; pthread_t thumbnailQueueThread;
bool thumbnailQueueRunning; bool thumbnailQueueRunning;
std::deque<ThumbnailRequest> thumbnailRequests; std::deque<ThumbnailRequest> thumbnailRequests;
@@ -91,10 +92,12 @@ private:
static void * thumbnailQueueProcessHelper(void * ref); static void * thumbnailQueueProcessHelper(void * ref);
void thumbnailQueueProcessTH(); void thumbnailQueueProcessTH();
void assureRunning();
public: public:
ThumbnailBroker(); ThumbnailBroker();
virtual ~ThumbnailBroker(); virtual ~ThumbnailBroker();
void Shutdown();
void FlushThumbQueue(); void FlushThumbQueue();
void RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener); void RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener);