From 12a05d41e9bafff37547c4cdfc2895fd8a5b21bd Mon Sep 17 00:00:00 2001 From: ac-stef Date: Thu, 17 Sep 2015 16:40:59 +0200 Subject: [PATCH] add interface for timedwait on semaphores According to SDL documentation, the SDL implementation of timedwait may suck on some platforms, so it should only be used, where high CPU usage during the wait is no issue. getpckserver() will now only wait for one second for access to the package server list and return an error instead of waiting indefinitely. --- source/src/Makefile | 2 +- source/src/autodownload.cpp | 11 +++++++---- source/src/tools.cpp | 19 +++++++++++++++++++ source/src/tools.h | 1 + 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/source/src/Makefile b/source/src/Makefile index 289f532b..09898b94 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -115,7 +115,7 @@ SERVER_INCLUDES= -DSTANDALONE $(INCLUDES) -I../include SERVER_LIBS= -L../lib -lzdll -lenet -lws2_32 -lwinmm else SERVER_INCLUDES= -DSTANDALONE $(INCLUDES) -SERVER_LIBS= -L../enet/.libs -lenet -lz -lpthread +SERVER_LIBS= -L../enet/.libs -lenet -lz -lpthread -lrt endif SERVER_OBJS= \ diff --git a/source/src/autodownload.cpp b/source/src/autodownload.cpp index 5d1562c6..21ef9a90 100644 --- a/source/src/autodownload.cpp +++ b/source/src/autodownload.cpp @@ -53,13 +53,16 @@ COMMAND(addpckserver, "ss"); void getpckserver() // return a table of all package servers with four columns { - sem_pckservers.wait(); vector res; - loopv(pckservers) cvecprintf(res, "\"%s\" %d %d %d\n", pckservers[i]->host, pckservers[i]->priority, pckservers[i]->ping, pckservers[i]->resolved); + if(sem_pckservers.timedwait(1000)) cvecprintf(res, "\"serverlist is busy, try again later\" "); // single-word return value signals an error + else + { + loopv(pckservers) cvecprintf(res, "\"%s\" %d %d %d\n", pckservers[i]->host, pckservers[i]->priority, pckservers[i]->ping, pckservers[i]->resolved); + sem_pckservers.post(); + } if(res.length()) res.last() = '\0'; else res.add('\0'); result(res.getbuf()); - sem_pckservers.post(); } COMMAND(getpckserver, ""); @@ -430,7 +433,7 @@ int downloadpackages(bool loadscr) // get all pending packages httpget h; canceldownloads = false; progress_of = loadscr ? pendingpackages.length() : -1; - if(sem_pckservers.trywait()) + if(sem_pckservers.timedwait(1000)) { // can't lock the server list -> this means, the server ping threads have not finished yet if(pendingpackages.length()) conoutf("\f3failed to download packages: still pinging the servers..."); return 0; diff --git a/source/src/tools.cpp b/source/src/tools.cpp index 9fbd49c8..c2e4405f 100644 --- a/source/src/tools.cpp +++ b/source/src/tools.cpp @@ -543,6 +543,11 @@ int sl_semaphore::trywait() return SDL_SemTryWait((SDL_sem *) data); } +int sl_semaphore::timedwait(int howlongmillis) +{ + return SDL_SemWaitTimeout((SDL_sem *) data, howlongmillis); +} + int sl_semaphore::getvalue() { return SDL_SemValue((SDL_sem *) data); @@ -579,6 +584,20 @@ int sl_semaphore::trywait() return sem_trywait((sem_t *) data); } +int sl_semaphore::timedwait(int howlongmillis) +{ + struct timespec t; + if(clock_gettime(CLOCK_REALTIME, &t)) + { + (*errorcount)++; + return sem_trywait((sem_t *) data); + } + howlongmillis += t.tv_nsec / 1000000; + t.tv_nsec = (howlongmillis % 1000) * 1000000; + t.tv_sec += howlongmillis / 1000; + return sem_timedwait((sem_t *) data, &t); +} + int sl_semaphore::getvalue() { int ret; diff --git a/source/src/tools.h b/source/src/tools.h index fa9f10f5..aed5182d 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -1004,6 +1004,7 @@ struct sl_semaphore ~sl_semaphore(); void wait(); // blocks, until semaphore gets available int trywait(); // returns 0, if semaphore was locked (like wait(), but returns !=0 instead of blocking) + int timedwait(int howlongmillis); // like trywait(), but waits for a litte before returning failure int getvalue(); // returns current semaphore value void post(); // increments (unlocks) semaphore };