UCommon
/usr/src/RPM/BUILD/ucommon-6.3.3/inc/commoncpp/thread.h
Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
00003 // Copyright (C) 2015 Cherokees of Idaho.
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free software
00019 // library without restriction.  Specifically, if other files instantiate
00020 // templates or use macros or inline functions from this file, or you compile
00021 // this file and link it with other files to produce an executable, this
00022 // file does not by itself cause the resulting executable to be covered by
00023 // the GNU General Public License.  This exception does not however
00024 // invalidate any other reasons why the executable file might be covered by
00025 // the GNU General Public License.
00026 //
00027 // This exception applies only to the code released under the name GNU
00028 // Common C++.  If you copy code from other releases into a copy of GNU
00029 // Common C++, as the General Public License permits, the exception does
00030 // not apply to the code that you add in this way.  To avoid misleading
00031 // anyone as to the status of such modified files, you must delete
00032 // this exception notice from them.
00033 //
00034 // If you write modifications of your own for GNU Common C++, it is your choice
00035 // whether to permit this exception to apply to your modifications.
00036 // If you do not wish that, delete this exception notice.
00037 //
00038 
00044 #ifndef COMMONCPP_THREAD_H_
00045 #define COMMONCPP_THREAD_H_
00046 
00047 #ifndef COMMONCPP_CONFIG_H_
00048 #include <commoncpp/config.h>
00049 #endif
00050 
00051 #ifndef COMMONCPP_STRING_H_
00052 #include <commoncpp/string.h>
00053 #endif
00054 
00055 #define ENTER_CRITICAL  enterMutex();
00056 #define LEAVE_CRITICAL  leaveMutex();
00057 
00058 #include <time.h>
00059 
00060 namespace ost {
00061 
00062 class __EXPORT Mutex : protected ucommon::RecursiveMutex
00063 {
00064 public:
00065     inline Mutex() : RecursiveMutex() {}
00066 
00067     inline void enterMutex(void)
00068         {RecursiveMutex::lock();}
00069 
00070     inline void leaveMutex(void)
00071         {RecursiveMutex::release();}
00072 
00073     inline bool tryEnterMutex(void)
00074         {return RecursiveMutex::lock(0l);}
00075 
00076     inline void enter(void)
00077         {RecursiveMutex::lock();}
00078 
00079     inline void leave(void)
00080         {RecursiveMutex::release();}
00081 
00082     inline bool test(void)
00083         {return RecursiveMutex::lock(0l);}
00084 
00085 };
00086 
00096 class __EXPORT MutexCounter : public Mutex
00097 {
00098 protected:
00099     volatile int    counter;
00100 
00101 public:
00105     MutexCounter();
00106 
00113     MutexCounter(int initial);
00114 
00115     int operator++();
00116     int operator--();
00117 };
00118 
00142 class __EXPORT MutexLock
00143 {
00144 private:
00145     Mutex& mutex;
00146 
00147 public:
00153     inline MutexLock( Mutex& _mutex ) : mutex( _mutex )
00154         { mutex.enterMutex(); }
00155 
00159     // this should be not-virtual
00160     inline ~MutexLock()
00161         { mutex.leaveMutex(); }
00162 };
00163 
00164 class __EXPORT ThreadLock : protected ucommon::ThreadLock
00165 {
00166 public:
00167     inline ThreadLock() : ucommon::ThreadLock() {}
00168 
00169     inline void readLock(void)
00170         {ucommon::ThreadLock::access();}
00171 
00172     inline void writeLock(void)
00173         {ucommon::ThreadLock::modify();}
00174 
00175     inline void tryReadLock(void)
00176         {ucommon::ThreadLock::access(0);}
00177 
00178     inline void tryWriteLock(void)
00179         {ucommon::ThreadLock::modify(0);}
00180 
00181     inline void unlock(void)
00182         {ucommon::ThreadLock::release();}
00183 };
00184 
00205 class __EXPORT ReadLock
00206 {
00207 private:
00208     ThreadLock& tl;
00209 
00210 public:
00216     inline ReadLock( ThreadLock& _tl ) : tl( _tl )
00217         { tl.readLock(); }
00221     // this should be not-virtual
00222     inline ~ReadLock()
00223         { tl.unlock(); }
00224 };
00225 
00246 class __EXPORT WriteLock
00247 {
00248 private:
00249     ThreadLock& tl;
00250 
00251 public:
00257     inline WriteLock( ThreadLock& _tl ) : tl( _tl )
00258         { tl.writeLock(); }
00262     // this should be not-virtual
00263     inline ~WriteLock()
00264         { tl.unlock(); }
00265 };
00266 
00267 class __EXPORT Conditional : private ucommon::Conditional
00268 {
00269 public:
00270     inline Conditional() : ucommon::Conditional() {}
00271 
00272     bool wait(timeout_t timeout, bool locked = false);
00273 
00274     void signal(bool broadcast);
00275 
00276     inline void enterMutex(void)
00277         {ucommon::Conditional::lock();}
00278 
00279     inline void leaveMutex(void)
00280         {ucommon::Conditional::unlock();}
00281 };
00282 
00283 class __EXPORT Semaphore : private ucommon::Semaphore
00284 {
00285 public:
00286     inline Semaphore(unsigned size = 0) : ucommon::Semaphore(size) {}
00287 
00288     inline bool wait(timeout_t timeout)
00289         {return ucommon::Semaphore::wait(timeout);}
00290 
00291     inline void wait(void)
00292         {ucommon::Semaphore::wait();}
00293 
00294     inline void post(void)
00295         {ucommon::Semaphore::release();}
00296 };
00297 
00317 class __EXPORT SemaphoreLock
00318 {
00319 private:
00320     Semaphore& sem;
00321 
00322 public:
00326     inline SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00327         { sem.wait(); }
00331     // this should be not-virtual
00332     inline ~SemaphoreLock()
00333         { sem.post(); }
00334 };
00335 
00336 class __EXPORT Event : private ucommon::TimedEvent
00337 {
00338 public:
00339     inline Event() : ucommon::TimedEvent() {}
00340 
00341     inline void wait(void)
00342         {ucommon::TimedEvent::wait();}
00343 
00344     inline bool wait(timeout_t timeout)
00345         {return ucommon::TimedEvent::wait(timeout);}
00346 
00347     inline void signal(void)
00348         {ucommon::TimedEvent::signal();}
00349 
00350     inline void reset(void)
00351         {ucommon::TimedEvent::reset();}
00352 
00353     inline void set(timeout_t timeout = 0)
00354         {ucommon::TimedEvent::set(timeout);}
00355 };
00356 
00357 class __EXPORT Thread : protected ucommon::JoinableThread
00358 {
00359 public:
00363     typedef enum Throw {
00364         throwNothing,  
00365         throwObject,   
00366         throwException 
00367     } Throw;
00368 
00369 private:
00370     friend class Slog;
00371 
00372     Throw exceptions;
00373     bool detached, terminated;
00374     Thread *parent;
00375     size_t msgpos;
00376     char msgbuf[128];
00377 
00378 public:
00379     Thread(int pri = 0, size_t stack = 0);
00380 
00381     virtual ~Thread();
00382 
00383     inline void map(void)
00384         {JoinableThread::map();}
00385 
00386     virtual void initial(void);
00387     virtual void notify(Thread *thread);
00388     virtual void final(void);
00389     virtual void run(void) = 0;
00390 
00391     void terminate(void);
00392     void finalize(void);
00393 
00394     void detach(void);
00395     void start(void);
00396     void exit(void);
00397 
00398     inline void join(void)
00399         {JoinableThread::join();}
00400 
00401     inline void sync(void)
00402         {Thread::exit();}
00403 
00404     static inline Thread *get(void)
00405         {return (Thread *)JoinableThread::get();}
00406 
00407     inline static void yield(void)
00408         {ucommon::Thread::yield();}
00409 
00410     inline static void sleep(timeout_t msec = TIMEOUT_INF)
00411         {ucommon::Thread::sleep(msec);}
00412 
00413     bool isRunning(void);
00414 
00415     bool isThread(void);
00416 
00422     static Throw getException(void);
00423 
00429     static void setException(Throw mode);
00430 
00434     inline pthread_t getId(void)
00435         {return tid;}
00436 };
00437 
00467 class __EXPORT SysTime
00468 {
00469 public:
00470     static time_t getTime(time_t *tloc = NULL);
00471     static time_t time(time_t *tloc)
00472         {return getTime(tloc);}
00473 
00474     static int getTimeOfDay(struct timeval *tp);
00475     static int gettimeofday(struct timeval *tp, struct timezone *)
00476         {return getTimeOfDay(tp);}
00477 
00478     static struct tm *getLocalTime(const time_t *clock, struct tm *result);
00479     static struct tm *locatime(const time_t *clock, struct tm *result)
00480         {return getLocalTime(clock, result);}
00481 
00482     static struct tm *getGMTTime(const time_t *clock, struct tm *result);
00483     static struct tm *gmtime(const time_t *clock, struct tm *result)
00484         {return getGMTTime(clock, result);}
00485 };
00486 
00497 class __EXPORT TimerPort
00498 {
00499 #ifndef _MSWINDOWS_
00500     struct timeval timer;
00501 #else
00502     DWORD timer;
00503 #endif
00504     bool active;
00505 
00506 public:
00513     TimerPort();
00514 
00523     void setTimer(timeout_t timeout = 0);
00524 
00534     void incTimer(timeout_t timeout);
00535 
00545     void decTimer(timeout_t timeout);
00546 
00551     void sleepTimer(void);
00552 
00558     void endTimer(void);
00559 
00571     timeout_t getTimer(void) const;
00572 
00582     timeout_t getElapsed(void) const;
00583 };
00584 
00585 #ifndef _MSWINDOWS_
00586 struct  timespec *getTimeout(struct timespec *spec, timeout_t timeout);
00587 #endif
00588 
00589 #if !defined(_MSWINDOWS_) || defined(_MSTHREADS_)
00590 inline struct tm *localtime_r(const time_t *t, struct tm *b)
00591     {return SysTime::getLocalTime(t, b);}
00592 
00593 inline char *ctime_r(const time_t *t, char *buf)
00594     {return ctime(t);}
00595 
00596 inline struct tm *gmtime_r(const time_t *t, struct tm *b)
00597     {return SysTime::getGMTTime(t, b);}
00598 
00599 inline char *asctime_r(const struct tm *tm, char *b)
00600     {return asctime(tm);}
00601 #endif
00602 
00603 inline Thread *getThread(void)
00604     {return Thread::get();}
00605 
00627 #ifdef  _MSWINDOWS_
00628 class __EXPORT Buffer : public Mutex
00629 #else
00630 class __EXPORT Buffer : public Conditional
00631 #endif
00632 {
00633 private:
00634 #ifdef  _MSWINDOWS_
00635     HANDLE  sem_head, sem_tail;
00636 #endif
00637     size_t _size;
00638     size_t _used;
00639 
00640 protected:
00646     virtual size_t onPeek(void *buf) = 0;
00647 
00653     virtual size_t onWait(void *buf) = 0;
00654 
00660     virtual size_t onPost(void *buf) = 0;
00661 
00662 public:
00667     static const size_t timeout;
00668 
00673     Buffer(size_t capacity);
00678     virtual ~Buffer();
00679 
00684     inline size_t getSize(void)
00685         {return _size;}
00686 
00693     inline size_t getUsed(void)
00694         {return _used;}
00695 
00705     size_t wait(void *buf, timeout_t timeout = 0);
00706 
00715     size_t post(void *buf, timeout_t timeout = 0);
00716 
00723     size_t peek(void *buf);
00724 
00729     virtual bool isValid(void);
00730 };
00731 
00739 class __EXPORT FixedBuffer : public Buffer
00740 {
00741 private:
00742     char *buf, *head, *tail;
00743     size_t objsize;
00744 
00745 protected:
00751     size_t onPeek(void *buf);
00752 
00758     size_t onWait(void *buf);
00759 
00765     size_t onPost(void *buf);
00766 
00767 public:
00775     FixedBuffer(size_t capacity, size_t objsize);
00776 
00783     FixedBuffer(const FixedBuffer &fb);
00784 
00788     virtual ~FixedBuffer();
00789 
00790     FixedBuffer &operator=(const FixedBuffer &fb);
00791 
00792     bool isValid(void);
00793 };
00794 
00810 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
00811 {
00812 private:
00813     void run(void);         // private run method
00814 
00815 protected:
00816     typedef struct _data {
00817         struct _data *next;
00818         unsigned len;
00819         char data[1];
00820     }   data_t;
00821 
00822     timeout_t timeout;
00823     bool started;
00824 
00825     data_t *first, *last;       // head/tail of list
00826 
00827     String name;
00828 
00829     /*
00830      * Overloading of final(). It demarks Semaphore to avoid deadlock.
00831      */
00832     virtual void final();
00833 
00838     virtual void startQueue(void);
00839 
00845     virtual void stopQueue(void);
00846 
00850     virtual void onTimer(void);
00851 
00860     virtual void runQueue(void *data) = 0;
00861 
00862 public:
00870     ThreadQueue(const char *id, int pri, size_t stack = 0);
00871 
00875     virtual ~ThreadQueue();
00876 
00884     void setTimer(timeout_t timeout);
00885 
00894     void post(const void *data, unsigned len);
00895 };
00896 
00897 
00899 inline size_t get(Buffer &b, void *o, timeout_t t = 0)
00900     {return b.wait(o, t);}
00901 
00903 inline size_t put(Buffer &b, void *o, timeout_t t = 0)
00904     {return b.post(o, t);}
00905 
00907 inline size_t peek(Buffer &b, void *o)
00908     {return b.peek(o);}
00909 
00910 } // namespace ost
00911 
00912 #endif