00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00043 #ifndef COMMONCPP_THREAD_H_
00044 #define COMMONCPP_THREAD_H_
00045
00046 #ifndef COMMONCPP_CONFIG_H_
00047 #include <commoncpp/config.h>
00048 #endif
00049
00050 #ifndef COMMONCPP_STRING_H_
00051 #include <commoncpp/string.h>
00052 #endif
00053
00054 #define ENTER_CRITICAL enterMutex();
00055 #define LEAVE_CRITICAL leaveMutex();
00056
00057 NAMESPACE_COMMONCPP
00058
00059 class __EXPORT Mutex : protected ucommon::RecursiveMutex
00060 {
00061 public:
00062 inline Mutex() : RecursiveMutex() {};
00063
00064 inline void enterMutex(void)
00065 {RecursiveMutex::lock();};
00066
00067 inline void leaveMutex(void)
00068 {RecursiveMutex::release();};
00069
00070 inline bool tryEnterMutex(void)
00071 {return RecursiveMutex::lock(0l);};
00072
00073 inline void enter(void)
00074 {RecursiveMutex::lock();};
00075
00076 inline void leave(void)
00077 {RecursiveMutex::release();};
00078
00079 inline bool test(void)
00080 {return RecursiveMutex::lock(0l);};
00081
00082 };
00083
00093 class __EXPORT MutexCounter : public Mutex
00094 {
00095 protected:
00096 volatile int counter;
00097
00098 public:
00102 MutexCounter();
00103
00110 MutexCounter(int initial);
00111
00112 int operator++();
00113 int operator--();
00114 };
00115
00139 class __EXPORT MutexLock
00140 {
00141 private:
00142 Mutex& mutex;
00143
00144 public:
00150 inline MutexLock( Mutex& _mutex ) : mutex( _mutex )
00151 { mutex.enterMutex(); }
00152
00156
00157 inline ~MutexLock()
00158 { mutex.leaveMutex(); }
00159 };
00160
00161 class __EXPORT ThreadLock : protected ucommon::ThreadLock
00162 {
00163 public:
00164 inline ThreadLock() : ucommon::ThreadLock() {};
00165
00166 inline void readLock(void)
00167 {ucommon::ThreadLock::access();};
00168
00169 inline void writeLock(void)
00170 {ucommon::ThreadLock::modify();};
00171
00172 inline void tryReadLock(void)
00173 {ucommon::ThreadLock::access(0);};
00174
00175 inline void tryWriteLock(void)
00176 {ucommon::ThreadLock::modify(0);};
00177
00178 inline void unlock(void)
00179 {ucommon::ThreadLock::release();};
00180 };
00181
00202 class __EXPORT ReadLock
00203 {
00204 private:
00205 ThreadLock& tl;
00206
00207 public:
00213 inline ReadLock( ThreadLock& _tl ) : tl( _tl )
00214 { tl.readLock(); }
00218
00219 inline ~ReadLock()
00220 { tl.unlock(); }
00221 };
00222
00243 class __EXPORT WriteLock
00244 {
00245 private:
00246 ThreadLock& tl;
00247
00248 public:
00254 inline WriteLock( ThreadLock& _tl ) : tl( _tl )
00255 { tl.writeLock(); }
00259
00260 inline ~WriteLock()
00261 { tl.unlock(); }
00262 };
00263
00264 class __EXPORT Conditional : private ucommon::Conditional
00265 {
00266 public:
00267 inline Conditional() : ucommon::Conditional() {};
00268
00269 bool wait(timeout_t timeout, bool locked = false);
00270
00271 void signal(bool broadcast);
00272
00273 inline void enterMutex(void)
00274 {ucommon::Conditional::lock();}
00275
00276 inline void leaveMutex(void)
00277 {ucommon::Conditional::unlock();}
00278 };
00279
00280 class __EXPORT Semaphore : private ucommon::Semaphore
00281 {
00282 public:
00283 inline Semaphore(unsigned size = 0) : ucommon::Semaphore(size) {};
00284
00285 inline bool wait(timeout_t timeout)
00286 {return ucommon::Semaphore::wait(timeout);}
00287
00288 inline void wait(void)
00289 {ucommon::Semaphore::wait();}
00290
00291 inline void post(void)
00292 {ucommon::Semaphore::release();}
00293 };
00294
00314 class __EXPORT SemaphoreLock
00315 {
00316 private:
00317 Semaphore& sem;
00318
00319 public:
00323 inline SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00324 { sem.wait(); }
00328
00329 inline ~SemaphoreLock()
00330 { sem.post(); }
00331 };
00332
00333 class __EXPORT Event : private ucommon::TimedEvent
00334 {
00335 public:
00336 inline Event() : ucommon::TimedEvent() {};
00337
00338 inline void wait(void)
00339 {ucommon::TimedEvent::wait();}
00340
00341 inline bool wait(timeout_t timeout)
00342 {return ucommon::TimedEvent::wait(timeout);}
00343
00344 inline void signal(void)
00345 {ucommon::TimedEvent::signal();}
00346
00347 inline void reset(void)
00348 {ucommon::TimedEvent::reset();}
00349
00350 inline void set(timeout_t timeout = 0)
00351 {ucommon::TimedEvent::set(timeout);}
00352 };
00353
00354 class __EXPORT Thread : protected ucommon::JoinableThread
00355 {
00356 public:
00360 typedef enum Throw {
00361 throwNothing,
00362 throwObject,
00363 throwException
00364 } Throw;
00365
00366 private:
00367 friend class Slog;
00368
00369 Throw exceptions;
00370 bool detached, terminated;
00371 Thread *parent;
00372 size_t msgpos;
00373 char msgbuf[128];
00374
00375 public:
00376 Thread(int pri = 0, size_t stack = 0);
00377
00378 virtual ~Thread();
00379
00380 inline void map(void)
00381 {JoinableThread::map();};
00382
00383 virtual void initial(void);
00384 virtual void notify(Thread *thread);
00385 virtual void final(void);
00386 virtual void run(void) = 0;
00387
00388 void terminate(void);
00389 void finalize(void);
00390
00391 void detach(void);
00392 void start(void);
00393 void exit(void);
00394
00395 inline void join(void)
00396 {JoinableThread::join();};
00397
00398 inline void sync(void)
00399 {Thread::exit();};
00400
00401 static inline Thread *get(void)
00402 {return (Thread *)JoinableThread::get();};
00403
00404 inline static void yield(void)
00405 {ucommon::Thread::yield();};
00406
00407 inline static void sleep(timeout_t msec = TIMEOUT_INF)
00408 {ucommon::Thread::sleep(msec);};
00409
00410 bool isRunning(void);
00411
00412 bool isThread(void);
00413
00419 static Throw getException(void);
00420
00426 static void setException(Throw mode);
00427
00431 inline pthread_t getId(void)
00432 {return tid;};
00433 };
00434
00464 class __EXPORT SysTime
00465 {
00466 public:
00467 static time_t getTime(time_t *tloc = NULL);
00468 static time_t time(time_t *tloc)
00469 { return getTime(tloc); };
00470
00471 static int getTimeOfDay(struct timeval *tp);
00472 static int gettimeofday(struct timeval *tp, struct timezone *)
00473 { return getTimeOfDay(tp); };
00474
00475 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
00476 static struct tm *locatime(const time_t *clock, struct tm *result)
00477 { return getLocalTime(clock, result); };
00478
00479 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
00480 static struct tm *gmtime(const time_t *clock, struct tm *result)
00481 { return getGMTTime(clock, result);};
00482 };
00483
00494 class __EXPORT TimerPort
00495 {
00496 #ifndef _MSWINDOWS_
00497 struct timeval timer;
00498 #else
00499 DWORD timer;
00500 #endif
00501 bool active;
00502
00503 public:
00510 TimerPort();
00511
00520 void setTimer(timeout_t timeout = 0);
00521
00531 void incTimer(timeout_t timeout);
00532
00542 void decTimer(timeout_t timeout);
00543
00548 void sleepTimer(void);
00549
00555 void endTimer(void);
00556
00568 timeout_t getTimer(void) const;
00569
00579 timeout_t getElapsed(void) const;
00580 };
00581
00582 #ifndef _MSWINDOWS_
00583 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
00584 #endif
00585
00586 inline struct tm *localtime_r(const time_t *t, struct tm *b)
00587 {return SysTime::getLocalTime(t, b);}
00588
00589 inline char *ctime_r(const time_t *t, char *buf)
00590 {return ctime(t);}
00591
00592 inline struct tm *gmtime_r(const time_t *t, struct tm *b)
00593 {return SysTime::getGMTTime(t, b);}
00594
00595 inline char *asctime_r(const struct tm *tm, char *b)
00596 {return asctime(tm);}
00597
00598 inline Thread *getThread(void)
00599 {return Thread::get();}
00600
00622 #ifdef _MSWINDOWS_
00623 class __EXPORT Buffer : public Mutex
00624 #else
00625 class __EXPORT Buffer : public Conditional
00626 #endif
00627 {
00628 private:
00629 #ifdef _MSWINDOWS_
00630 HANDLE sem_head, sem_tail;
00631 #endif
00632 size_t _size;
00633 size_t _used;
00634
00635 protected:
00641 virtual size_t onPeek(void *buf) = 0;
00642
00648 virtual size_t onWait(void *buf) = 0;
00649
00655 virtual size_t onPost(void *buf) = 0;
00656
00657 public:
00662 static const size_t timeout;
00663
00668 Buffer(size_t capacity);
00673 virtual ~Buffer();
00674
00679 inline size_t getSize(void)
00680 {return _size;};
00681
00688 inline size_t getUsed(void)
00689 {return _used;};
00690
00700 size_t wait(void *buf, timeout_t timeout = 0);
00701
00710 size_t post(void *buf, timeout_t timeout = 0);
00711
00718 size_t peek(void *buf);
00719
00724 virtual bool isValid(void);
00725 };
00726
00734 class __EXPORT FixedBuffer : public Buffer
00735 {
00736 private:
00737 char *buf, *head, *tail;
00738 size_t objsize;
00739
00740 protected:
00746 size_t onPeek(void *buf);
00747
00753 size_t onWait(void *buf);
00754
00760 size_t onPost(void *buf);
00761
00762 public:
00770 FixedBuffer(size_t capacity, size_t objsize);
00771
00778 FixedBuffer(const FixedBuffer &fb);
00779
00783 virtual ~FixedBuffer();
00784
00785 FixedBuffer &operator=(const FixedBuffer &fb);
00786
00787 bool isValid(void);
00788 };
00789
00805 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
00806 {
00807 private:
00808 void run(void);
00809
00810 protected:
00811 typedef struct _data {
00812 struct _data *next;
00813 unsigned len;
00814 char data[1];
00815 } data_t;
00816
00817 timeout_t timeout;
00818 bool started;
00819
00820 data_t *first, *last;
00821
00822 String name;
00823
00824
00825
00826
00827 virtual void final();
00828
00833 virtual void startQueue(void);
00834
00840 virtual void stopQueue(void);
00841
00845 virtual void onTimer(void);
00846
00855 virtual void runQueue(void *data) = 0;
00856
00857 public:
00865 ThreadQueue(const char *id, int pri, size_t stack = 0);
00866
00870 virtual ~ThreadQueue();
00871
00879 void setTimer(timeout_t timeout);
00880
00889 void post(const void *data, unsigned len);
00890 };
00891
00892
00894 inline size_t get(Buffer &b, void *o, timeout_t t = 0)
00895 {return b.wait(o, t);}
00896
00898 inline size_t put(Buffer &b, void *o, timeout_t t = 0)
00899 {return b.post(o, t);}
00900
00902 inline size_t peek(Buffer &b, void *o)
00903 {return b.peek(o);}
00904
00905 END_NAMESPACE
00906
00907 #endif