Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 252 lines (178 sloc) 4.35 KB
#ifndef com_sleepless_object_cpp
#define com_sleepless_object_cpp
// Copyright 1998-2004
// Sleepless Software Inc.
// All Rights Reserved
#ifdef WIN32
#include <windows.h>
#include "System.cpp"
struct Object
{
HANDLE event;
public: Object()
{
//event = CreateEvent( NULL, FALSE, FALSE, NULL);
event = CreateEvent( NULL, TRUE, FALSE, NULL);
// What are the chances of this ever failing?
// if(event == NULL) ...
}
public: ~Object()
{
CloseHandle(event);
}
// wake up exactly one thread waiting on this object
public: void notify()
{
PulseEvent(event);
}
// wake up all threads waiting on this object
public: void notifyAll()
{
PulseEvent(event);
}
// put thread to sleep until notified
public: void wait()
{
WaitForSingleObject(event, INFINITE);
}
// returns false if notified, true if timed out
public: bool wait(long millis)
{
return WaitForSingleObject(event, millis) == WAIT_TIMEOUT;
}
};
#endif
#if defined(linux) || (defined(__APPLE__) && defined(__GNUC__))
#include <sys/time.h>
#include <pthread.h>
#include <errno.h>
class Object
{
pthread_cond_t cond;
pthread_mutex_t mutex;
public: Object()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
}
// wake up exactly one thread waiting on this object
public: void notify()
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
// wake up all threads waiting on this object
public: void notifyAll()
{
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
// put thread to sleep until notified
public: void wait()
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
}
// returns false if notified, true if timed out
public: bool wait(long millis)
{
pthread_mutex_lock(&mutex);
struct timespec ts;
struct timeval tp;
gettimeofday(&tp, 0);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_sec += (millis / 1000);
ts.tv_nsec += ((millis % 1000) * 1000);
// XXX
// I really don't know what happens if the tv_nsec value is
// actually large enough to constitute one or more whole seconds.
// Hopefully, whoever ends up making use of the timespec takes this
// into account. j.h.
// XXX
int rc = pthread_cond_timedwait(&cond, &mutex, &ts);
pthread_mutex_unlock(&mutex);
return rc == ETIMEDOUT;
}
};
#endif
#ifdef TEST_OBJECT
#include <stdio.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include "Thread.cpp"
Object obj;
void *func(void *parm)
{
printf("Thread %d waiting\n", (int)parm);
obj.wait();
printf("Thread %d woke\n", (int)parm);
return 0;
}
void *func2(void *parm)
{
printf("Thread %d waiting (max 4 secs)\n", (int)parm);
if(obj.wait(4000))
printf("Thread %d timed out\n", (int)parm);
else
printf("Thread %d woke\n", (int)parm);
return 0;
}
int main(int argc, char **argv)
{
Thread th1(func);
Thread th2(func);
Thread th3(func);
Thread th4(func2);
printf("main starting thread 4\n");
th4.start((void *)4);
printf("main sleeping 2 secs ...\n");
System::ssleep(2);
printf("main notifying 1 thread ...\n");
obj.notify();
printf("main joining thread 4 ...\n");
Thread::join(&th4);
System::ssleep(1);
printf("main starting thread 4 again\n");
th4.start((void *)4);
printf("main sleeping 6 secs ...\n");
System::ssleep(6);
printf("main (pointlessly) notifying 1 thread ...\n");
obj.notify();
printf("main joining thread 4 ...\n");
Thread::join(&th4);
System::ssleep(1); printf("-----\n");
printf("main starting thread 1\n");
th1.start((void *)1);
printf("main sleeping 3 secs ...\n");
System::ssleep(3);
printf("main notifying 1 thread ...\n");
obj.notify();
printf("main joining thread 1 ...\n");
Thread::join(&th1);
System::ssleep(1); printf("-----\n");
printf("main starting thread 1\n");
th1.start((void *)1);
printf("main starting thread 2\n");
th2.start((void *)2);
printf("main starting thread 3\n");
th3.start((void *)3);
printf("main sleeping 4 secs ...\n");
System::ssleep(4);
printf("main notifying all ...\n");
obj.notifyAll();
printf("main joining thread 1 ...\n");
Thread::join(&th1);
printf("main joining thread 2 ...\n");
Thread::join(&th2);
printf("main joining thread 3 ...\n");
Thread::join(&th3);
printf("main exit\n");
return 0;
}
#endif
#endif // com_sleepless_object_cpp