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.
This commit is contained in:
+1
-1
@@ -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= \
|
||||
|
||||
@@ -53,13 +53,16 @@ COMMAND(addpckserver, "ss");
|
||||
|
||||
void getpckserver() // return a table of all package servers with four columns
|
||||
{
|
||||
sem_pckservers.wait();
|
||||
vector<char> 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user