ucommon
|
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation. 00002 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks. 00003 // 00004 // This program is free software; you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation; either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00023 #ifndef COMMONCPP_THREAD_H_ 00024 #define COMMONCPP_THREAD_H_ 00025 00026 #ifndef COMMONCPP_CONFIG_H_ 00027 #include <commoncpp/config.h> 00028 #endif 00029 00030 #ifndef COMMONCPP_STRING_H_ 00031 #include <commoncpp/string.h> 00032 #endif 00033 00034 #define ENTER_CRITICAL enterMutex(); 00035 #define LEAVE_CRITICAL leaveMutex(); 00036 00037 NAMESPACE_COMMONCPP 00038 00039 class __EXPORT Mutex : protected ucommon::RecursiveMutex 00040 { 00041 public: 00042 inline Mutex() : RecursiveMutex() {}; 00043 00044 inline void enterMutex(void) 00045 {RecursiveMutex::lock();}; 00046 00047 inline void leaveMutex(void) 00048 {RecursiveMutex::release();}; 00049 00050 inline bool tryEnterMutex(void) 00051 {return RecursiveMutex::lock(0l);}; 00052 00053 inline void enter(void) 00054 {RecursiveMutex::lock();}; 00055 00056 inline void leave(void) 00057 {RecursiveMutex::release();}; 00058 00059 inline bool test(void) 00060 {return RecursiveMutex::lock(0l);}; 00061 00062 }; 00063 00073 class __EXPORT MutexCounter : public Mutex 00074 { 00075 protected: 00076 volatile int counter; 00077 00078 public: 00082 MutexCounter(); 00083 00090 MutexCounter(int initial); 00091 00092 int operator++(); 00093 int operator--(); 00094 }; 00095 00119 class __EXPORT MutexLock 00120 { 00121 private: 00122 Mutex& mutex; 00123 00124 public: 00130 inline MutexLock( Mutex& _mutex ) : mutex( _mutex ) 00131 { mutex.enterMutex(); } 00132 00136 // this should be not-virtual 00137 inline ~MutexLock() 00138 { mutex.leaveMutex(); } 00139 }; 00140 00141 class __EXPORT ThreadLock : protected ucommon::ThreadLock 00142 { 00143 public: 00144 inline ThreadLock() : ucommon::ThreadLock() {}; 00145 00146 inline void readLock(void) 00147 {ucommon::ThreadLock::access();}; 00148 00149 inline void writeLock(void) 00150 {ucommon::ThreadLock::modify();}; 00151 00152 inline void tryReadLock(void) 00153 {ucommon::ThreadLock::access(0);}; 00154 00155 inline void tryWriteLock(void) 00156 {ucommon::ThreadLock::modify(0);}; 00157 00158 inline void unlock(void) 00159 {ucommon::ThreadLock::release();}; 00160 }; 00161 00182 class __EXPORT ReadLock 00183 { 00184 private: 00185 ThreadLock& tl; 00186 00187 public: 00193 inline ReadLock( ThreadLock& _tl ) : tl( _tl ) 00194 { tl.readLock(); } 00198 // this should be not-virtual 00199 inline ~ReadLock() 00200 { tl.unlock(); } 00201 }; 00202 00223 class __EXPORT WriteLock 00224 { 00225 private: 00226 ThreadLock& tl; 00227 00228 public: 00234 inline WriteLock( ThreadLock& _tl ) : tl( _tl ) 00235 { tl.writeLock(); } 00239 // this should be not-virtual 00240 inline ~WriteLock() 00241 { tl.unlock(); } 00242 }; 00243 00244 class __EXPORT Conditional : private ucommon::Conditional 00245 { 00246 public: 00247 inline Conditional() : ucommon::Conditional() {}; 00248 00249 bool wait(timeout_t timeout, bool locked = false); 00250 00251 void signal(bool broadcast); 00252 00253 inline void enterMutex(void) 00254 {ucommon::Conditional::lock();}; 00255 00256 inline void leaveMutex(void) 00257 {ucommon::Conditional::unlock();}; 00258 }; 00259 00260 class __EXPORT Semaphore : private ucommon::Semaphore 00261 { 00262 public: 00263 inline Semaphore(unsigned size) : ucommon::Semaphore(size) {}; 00264 00265 inline bool wait(timeout_t timeout = 0) 00266 {return ucommon::Semaphore::wait(timeout);}; 00267 00268 inline void post(void) 00269 {ucommon::Semaphore::release();}; 00270 }; 00271 00291 class __EXPORT SemaphoreLock 00292 { 00293 private: 00294 Semaphore& sem; 00295 00296 public: 00300 inline SemaphoreLock( Semaphore& _sem ) : sem( _sem ) 00301 { sem.wait(); } 00305 // this should be not-virtual 00306 inline ~SemaphoreLock() 00307 { sem.post(); } 00308 }; 00309 00310 class __EXPORT Event : private ucommon::TimedEvent 00311 { 00312 public: 00313 inline Event() : TimedEvent() {}; 00314 00315 inline void wait(void) 00316 {ucommon::TimedEvent::wait(Timer::inf);}; 00317 00318 inline bool wait(timeout_t timeout) 00319 {return ucommon::TimedEvent::wait(timeout);}; 00320 00321 inline void signal(void) 00322 {ucommon::TimedEvent::signal();}; 00323 00324 inline void reset(void) 00325 {ucommon::TimedEvent::reset();}; 00326 }; 00327 00328 class __EXPORT Thread : protected ucommon::JoinableThread 00329 { 00330 public: 00334 typedef enum Throw { 00335 throwNothing, 00336 throwObject, 00337 throwException 00338 } Throw; 00339 00340 private: 00341 friend class Slog; 00342 00343 Throw exceptions; 00344 bool detached, terminated; 00345 Thread *parent; 00346 size_t msgpos; 00347 char msgbuf[128]; 00348 00349 public: 00350 Thread(int pri = 0, size_t stack = 0); 00351 00352 virtual ~Thread(); 00353 00354 inline void map(void) 00355 {JoinableThread::map();}; 00356 00357 virtual void initial(void); 00358 virtual void notify(Thread *thread); 00359 virtual void final(void); 00360 virtual void run(void) = 0; 00361 00362 void terminate(void); 00363 void finalize(void); 00364 00365 void detach(void); 00366 void start(void); 00367 void exit(void); 00368 00369 inline void join(void) 00370 {JoinableThread::join();}; 00371 00372 inline void sync(void) 00373 {Thread::exit();}; 00374 00375 static inline Thread *get(void) 00376 {return (Thread *)JoinableThread::get();}; 00377 00378 inline static void yield(void) 00379 {ucommon::Thread::yield();}; 00380 00381 inline static void sleep(timeout_t msec = TIMEOUT_INF) 00382 {ucommon::Thread::sleep(msec);}; 00383 00384 bool isRunning(void); 00385 00386 bool isThread(void); 00387 00393 static Throw getException(void); 00394 00400 static void setException(Throw mode); 00401 00405 inline pthread_t getId(void) 00406 {return tid;}; 00407 }; 00408 00438 class __EXPORT SysTime 00439 { 00440 public: 00441 static time_t getTime(time_t *tloc = NULL); 00442 static time_t time(time_t *tloc) 00443 { return getTime(tloc); }; 00444 00445 static int getTimeOfDay(struct timeval *tp); 00446 static int gettimeofday(struct timeval *tp, struct timezone *) 00447 { return getTimeOfDay(tp); }; 00448 00449 static struct tm *getLocalTime(const time_t *clock, struct tm *result); 00450 static struct tm *locatime(const time_t *clock, struct tm *result) 00451 { return getLocalTime(clock, result); }; 00452 00453 static struct tm *getGMTTime(const time_t *clock, struct tm *result); 00454 static struct tm *gmtime(const time_t *clock, struct tm *result) 00455 { return getGMTTime(clock, result);}; 00456 }; 00457 00468 class __EXPORT TimerPort 00469 { 00470 #ifndef _MSWINDOWS_ 00471 struct timeval timer; 00472 #else 00473 DWORD timer; 00474 #endif 00475 bool active; 00476 00477 public: 00484 TimerPort(); 00485 00494 void setTimer(timeout_t timeout = 0); 00495 00505 void incTimer(timeout_t timeout); 00506 00516 void decTimer(timeout_t timeout); 00517 00522 void sleepTimer(void); 00523 00529 void endTimer(void); 00530 00542 timeout_t getTimer(void) const; 00543 00553 timeout_t getElapsed(void) const; 00554 }; 00555 00556 #ifndef _MSWINDOWS_ 00557 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout); 00558 #endif 00559 00560 inline struct tm *localtime_r(const time_t *t, struct tm *b) 00561 {return SysTime::getLocalTime(t, b);} 00562 00563 inline char *ctime_r(const time_t *t, char *buf) 00564 {return ctime(t);} 00565 00566 inline struct tm *gmtime_r(const time_t *t, struct tm *b) 00567 {return SysTime::getGMTTime(t, b);} 00568 00569 inline char *asctime_r(const struct tm *tm, char *b) 00570 {return asctime(tm);} 00571 00572 inline Thread *getThread(void) 00573 {return Thread::get();} 00574 00596 #ifdef _MSWINDOWS_ 00597 class __EXPORT Buffer : public Mutex 00598 #else 00599 class __EXPORT Buffer : public Conditional 00600 #endif 00601 { 00602 private: 00603 #ifdef _MSWINDOWS_ 00604 HANDLE sem_head, sem_tail; 00605 #endif 00606 size_t _size; 00607 size_t _used; 00608 00609 protected: 00615 virtual size_t onPeek(void *buf) = 0; 00616 00622 virtual size_t onWait(void *buf) = 0; 00623 00629 virtual size_t onPost(void *buf) = 0; 00630 00631 public: 00636 static const size_t timeout; 00637 00642 Buffer(size_t capacity); 00647 virtual ~Buffer(); 00648 00653 inline size_t getSize(void) 00654 {return _size;}; 00655 00662 inline size_t getUsed(void) 00663 {return _used;}; 00664 00674 size_t wait(void *buf, timeout_t timeout = 0); 00675 00684 size_t post(void *buf, timeout_t timeout = 0); 00685 00692 size_t peek(void *buf); 00693 00698 virtual bool isValid(void); 00699 }; 00700 00708 class __EXPORT FixedBuffer : public Buffer 00709 { 00710 private: 00711 char *buf, *head, *tail; 00712 size_t objsize; 00713 00714 protected: 00720 size_t onPeek(void *buf); 00721 00727 size_t onWait(void *buf); 00728 00734 size_t onPost(void *buf); 00735 00736 public: 00744 FixedBuffer(size_t capacity, size_t objsize); 00745 00752 FixedBuffer(const FixedBuffer &fb); 00753 00757 virtual ~FixedBuffer(); 00758 00759 FixedBuffer &operator=(const FixedBuffer &fb); 00760 00761 bool isValid(void); 00762 }; 00763 00779 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore 00780 { 00781 private: 00782 void run(void); // private run method 00783 00784 protected: 00785 typedef struct _data { 00786 struct _data *next; 00787 unsigned len; 00788 char data[1]; 00789 } data_t; 00790 00791 timeout_t timeout; 00792 bool started; 00793 00794 data_t *first, *last; // head/tail of list 00795 00796 String name; 00797 00798 /* 00799 * Overloading of final(). It demarks Semaphore to avoid deadlock. 00800 */ 00801 virtual void final(); 00802 00807 virtual void startQueue(void); 00808 00814 virtual void stopQueue(void); 00815 00819 virtual void onTimer(void); 00820 00829 virtual void runQueue(void *data) = 0; 00830 00831 public: 00839 ThreadQueue(const char *id, int pri, size_t stack = 0); 00840 00844 virtual ~ThreadQueue(); 00845 00853 void setTimer(timeout_t timeout); 00854 00863 void post(const void *data, unsigned len); 00864 }; 00865 00866 00868 inline size_t get(Buffer &b, void *o, timeout_t t = 0) 00869 {return b.wait(o, t);} 00870 00872 inline size_t put(Buffer &b, void *o, timeout_t t = 0) 00873 {return b.post(o, t);} 00874 00876 inline size_t peek(Buffer &b, void *o) 00877 {return b.peek(o);} 00878 00879 END_NAMESPACE 00880 00881 #endif