IBR-DTNSuite  0.8
ibrcommon/ibrcommon/thread/Conditional.h
Go to the documentation of this file.
00001 #ifndef IBRCOMMON_CONDITIONAL_H_
00002 #define IBRCOMMON_CONDITIONAL_H_
00003 
00004 #include <stdlib.h>
00005 #include <errno.h>
00006 #include <pthread.h>
00007 #include "ibrcommon/thread/Mutex.h"
00008 #include "ibrcommon/Exceptions.h"
00009 
00010 namespace ibrcommon
00011 {
00012         class Conditional : public Mutex
00013         {
00014                 public:
00015                         class ConditionalAbortException : public ibrcommon::Exception
00016                         {
00017                         public:
00018                                 enum abort_t
00019                                 {
00020                                         COND_TIMEOUT = 0,
00021                                         COND_ABORT = 1,
00022                                         COND_ERROR = 2
00023                                 };
00024 
00025                                 ConditionalAbortException(abort_t abort, string what = "Conditional has been unblocked.") throw() : ibrcommon::Exception(what), reason(abort)
00026                                 {
00027                                 };
00028 
00029                                 const abort_t reason;
00030                         };
00031 
00032                         Conditional();
00033                         virtual ~Conditional();
00034 
00035                         void signal(bool broadcast = false);
00036 
00037                         /*
00038                          * Wait until signal() is called or the timeout exceeds.
00039                          * @param timeout A timeout in milliseconds.
00040                          * @throw ConditionalAbortException If a timeout occur or the Conditional is aborted by abort() the ConditionalAbortException is thrown.
00041                          */
00042                         void wait(size_t timeout = 0) throw (ConditionalAbortException);
00043                         void wait(struct timespec *ts) throw (ConditionalAbortException);
00044 
00048                         void abort();
00049 
00053                         void reset();
00054 
00061                         static void gettimeout(size_t timeout, struct timespec *hires);
00062 
00063                 private:
00064                         bool isLocked();
00065 
00066                         class attribute
00067                         {
00068                         public:
00069                                 pthread_condattr_t attr;
00070                                 attribute();
00071                         };
00072 
00073                         pthread_cond_t cond;
00074 
00075                         static attribute attr;
00076 
00077                         bool _abort;
00078         };
00079 
00080         template<class T, T block>
00081         class StatefulConditional : public Conditional
00082         {
00083         public:
00084                 StatefulConditional(T state) : _state(state) {};
00085                 virtual ~StatefulConditional() {};
00086 
00087                 void setState(T state)
00088                 {
00089                         if (ifState(block)) return;
00090                         _state = state;
00091                         this->signal(true);
00092                 }
00093 
00094                 bool waitState(T state)
00095                 {
00096                         while (!ifState(state))
00097                         {
00098                                 if (ifState(block)) return false;
00099                                 wait();
00100                         }
00101 
00102                         return true;
00103                 }
00104 
00105                 T getState()
00106                 {
00107                         return _state;
00108                 }
00109 
00110                 bool ifState(T state)
00111                 {
00112                         return (state == _state);
00113                 }
00114 
00115         private:
00116                 T _state;
00117         };
00118 }
00119 
00120 #endif /*CONDITIONAL_H_*/