0 comments
Published Thursday, March 09, 2006 by Dave.
I recently found myself needing a way to wait for a thread to complete without blocking indefinitely in the case that the waitee runs indefinitely. So i thought, hey I'll just call wait_with_timeout (or whatever pthreads calls it), and I'll be set. In win32 they have this, it's implemented via the ubiquitous WaitForSingleObject(), and you just pass the thread handle and a timeout.Well, the only problem is that pthreads just doesn't have this api. Only thing (that I can find), is pthread_join(). This will however, block the calling thread until the waitee finishes, or the calling thread is pthread_cancel()ed. So I started thinking about what I can do to implement something like the WaitForSingleObject() behavior, and this is what I came up with:
#include <stdio.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/select.h>
#define PTHREAD_JOIN_POLL_INTERVAL 10
#define false 0
#define true (!false)
typedef struct _waitData waitData;
struct _waitData
{
pthread_t waitID;
pthread_t helpID;
int done;
};
void
sleep_msecs(int msecs)
{
struct timeval tv;
tv.tv_sec = msecs/1000;
tv.tv_usec = (msecs % 1000) * 1000;
select (0,NULL,NULL,NULL,&tv);
}
unsigned int
get_ticks()
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_usec/1000 + tv.tv_sec * 1000);
}
void *
join_timeout_helper(void *arg)
{
waitData *data = (waitData*)arg;
pthread_join(data->waitID, NULL);
data->done = true;
return (void *)0;
}
int
pthread_join_timeout(pthread_t wid, int msecs)
{
pthread_t id;
waitData data;
unsigned int start = get_ticks();
int timedOut = false;
data.waitID = wid;
data.done = false;
if (pthread_create(&id, NULL, join_timeout_helper, &data) != 0)
return (-1);
do {
if (data.done)
break;
/* you could also yield to your message loop here... */
sleep_msecs(PTHREAD_JOIN_POLL_INTERVAL);
} while ((get_ticks() - start) < msecs);
if (!data.done)
{
pthread_cancel(id);
timedOut = true;
}
/* free helper thread resources */
pthread_join(id, NULL);
return (timedOut);
}
It seems like a lot of effort for what I'm getting in return, but it seems to work pretty well. I'm a little bit concerned about the overhead of spinning off a new thread to handle this, but at least on Linux this is (fairly) cheap. The code runs on OS X without modification as well.
0 comments
Published Wednesday, March 08, 2006 by Dave.
Oh wait. I spent a few hours today dinking with Xcode and the so called 10.1.5 SDK. That is what I call a serious joke.
The first issue:
#include <sys/poll.h>
Apple has a bug in their legacy SDK in that they fail to include this header, and the related library (yes, there appears to be a separate library for poll. Whatever.). So, I'm moving to the land of oh joy private copies of system headers and run time linking. Laaaame.