00001 #ifndef _LOCKED_SIGNAL_H
00002 #define _LOCKED_SIGNAL_H
00003
00004 #include "ScopedLock.h"
00005 #include "TimeUtil.h"
00006 #include <errno.h>
00007
00008 class LockedSignal {
00009 public:
00010 LockedSignal() : waiting(false), signalled(false) {
00011 ASSERT(pthread_mutex_init(&mutex, 0) == 0);
00012 ASSERT(pthread_cond_init(&cond, 0) == 0);
00013 }
00014
00015 virtual ~LockedSignal() {
00016 pthread_mutex_destroy(&mutex);
00017 pthread_cond_destroy(&cond);
00018 }
00019
00020 void signal() {
00021 ScopedLock sl(mutex);
00022 if (!signalled) {
00023 signalled = true;
00024 if (waiting) {
00025 pthread_cond_signal(&cond);
00026 }
00027 }
00028 }
00029
00030 int wait(uint64_t usec = 0) {
00031 if (usec == 0) {
00032 return lockWait(0);
00033 }
00034 else {
00035 struct timeval t;
00036 struct timespec ts;
00037 uint64_t fintime = TimeUtil::timeu() + usec;
00038 TimeUtil::fillTimeval(fintime, t);
00039 ts.tv_sec = t.tv_sec;
00040 ts.tv_nsec = t.tv_usec * 1000;
00041 return lockWait(&ts);
00042 }
00043 }
00044
00045 protected:
00046
00047 int lockWait(const struct timespec* ts) {
00048 int r = 1;
00049 ScopedLock sl(mutex);
00050 if (!signalled) {
00051 waiting = true;
00052 if (ts) {
00053 r = pthread_cond_timedwait(&cond, &mutex, ts);
00054 }
00055 else {
00056 pthread_cond_wait(&cond, &mutex);
00057 }
00058 }
00059 waiting = false;
00060 signalled = false;
00061 return r != ETIMEDOUT;
00062 }
00063
00064 private:
00065 bool waiting;
00066 bool signalled;
00067 pthread_mutex_t mutex;
00068 pthread_cond_t cond;
00069 };
00070
00071
00072 #endif // _LOCKED_SIGNAL_H