Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

thread.h

Go to the documentation of this file.
00001 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
00002 //  
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 // 
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 // 
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software 
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 // 
00017 // As a special exception, you may use this file as part of a free software
00018 // library without restriction.  Specifically, if other files instantiate
00019 // templates or use macros or inline functions from this file, or you compile
00020 // this file and link it with other files to produce an executable, this
00021 // file does not by itself cause the resulting executable to be covered by
00022 // the GNU General Public License.  This exception does not however    
00023 // invalidate any other reasons why the executable file might be covered by
00024 // the GNU General Public License.    
00025 //
00026 // This exception applies only to the code released under the name GNU
00027 // Common C++.  If you copy code from other releases into a copy of GNU
00028 // Common C++, as the General Public License permits, the exception does
00029 // not apply to the code that you add in this way.  To avoid misleading
00030 // anyone as to the status of such modified files, you must delete
00031 // this exception notice from them.
00032 //
00033 // If you write modifications of your own for GNU Common C++, it is your choice
00034 // whether to permit this exception to apply to your modifications.
00035 // If you do not wish that, delete this exception notice.
00036 //
00037 
00043 #ifndef CCXX_THREAD_H_
00044 #define CCXX_THREAD_H_
00045 
00046 #ifndef WIN32
00047 #define CCXX_POSIX
00048 #endif // !WIN32
00049 
00050 #ifndef CCXX_CONFIG_H_
00051 #include <cc++/config.h>
00052 #endif
00053 
00054 #include <ctime>
00055 
00056 #ifndef WIN32
00057 #include <pthread.h>
00058 #endif // !WIN32
00059 
00060 #undef CCXX_USE_WIN32_ATOMIC
00061 #ifndef WIN32
00062 #include <time.h>
00063 #include <signal.h>
00064 #include <unistd.h>
00065 
00066 #ifdef  _THR_UNIXWARE
00067 #undef  PTHREAD_MUTEXTYPE_RECURSIVE
00068 #endif
00069 
00070 typedef pthread_t       cctid_t;
00071 typedef unsigned long   timeout_t;
00072 
00073 /*
00074 #if defined(__CYGWIN32__)
00075 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00076 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00077 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00078 #define CCXX_USE_WIN32_ATOMIC 1
00079 #endif
00080 */
00081 
00082 #else // WIN32
00083 typedef DWORD   cctid_t;
00084 typedef DWORD   timeout_t;
00085 
00086 #define MAX_SEM_VALUE   1000000
00087 #define CCXX_USE_WIN32_ATOMIC 1
00088 
00089 #endif // !WIN32
00090 
00091 #ifdef  CCXX_NAMESPACES
00092 namespace ost {
00093 #endif
00094 
00095 class __EXPORT Thread;
00096 class __EXPORT ThreadKey;
00097 
00098 #define TIMEOUT_INF ~((timeout_t) 0)
00099 
00100 #define ENTER_CRITICAL  enterMutex();
00101 #define LEAVE_CRITICAL  leaveMutex();
00102 #define ENTER_DEFERRED  setCancel(cancelDeferred);
00103 #define LEAVE_DEFERRED  setCancel(cancelImmediate);
00104 
00105 #ifndef WIN32
00106 // These macros override common functions with thread-safe versions. In
00107 // particular the common "libc" sleep() has problems since it normally
00108 // uses SIGARLM (as actually defined by "posix").  The pthread_delay and
00109 // usleep found in libpthread are gaurenteed not to use SIGALRM and offer
00110 // higher resolution.  psleep() is defined to call the old process sleep.
00111 
00112 #undef  sleep
00113 #define psleep(x)       (sleep)(x)
00114 
00115 #ifdef  signal
00116 #undef  signal
00117 #endif
00118 
00119 #endif // !WIN32
00120 
00121 #undef Yield
00122 
00123 class __EXPORT Conditional;
00124 class __EXPORT Event;
00125 
00169 class __EXPORT Mutex
00170 {
00171 private:
00172         static bool _debug;
00173         const char *_name;
00174 #ifndef WIN32
00175 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00176         int volatile _level;
00177         Thread *volatile _tid;
00178 #endif
00179         /*
00180          * Pthread mutex object.  This is protected rather than private
00181          * because some mixed mode pthread operations require a mutex as
00182          * well as their primary pthread object.  A good example of this
00183          * is the Event class, as waiting on a conditional object must be
00184          * associated with an accessable mutex.  An alternative would be
00185          * to make such classes "friend" classes of the Mutex.
00186          */
00187         pthread_mutex_t _mutex;
00188 #else // WIN32
00189 
00190 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00191 # error "Can't determine underground for Mutex"
00192 # endif
00193 
00194 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX 
00195         HANDLE _mutex;
00196 #endif
00197 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION 
00198         CRITICAL_SECTION _criticalSection;
00199 #endif
00200 
00201 #endif // WIN32
00202 
00203 public:
00207         Mutex(const char *name = NULL);
00208 
00214         virtual ~Mutex();
00215 
00221         static void setDebug(bool mode)
00222                 {_debug = mode;};
00223 
00231         void enterMutex(void);
00232 
00236         inline void enter(void)
00237                 {enterMutex();};
00238 
00239         inline void leave(void)
00240                 {leaveMutex();};
00241 
00242         inline bool test(void)
00243                 {return tryEnterMutex();};
00244 
00255         bool tryEnterMutex(void);
00256 
00267         void leaveMutex(void);
00268 };
00269 
00293 class __EXPORT MutexLock
00294 {
00295 private:
00296         Mutex& mutex;
00297 public:
00301         MutexLock( Mutex& _mutex ) : mutex( _mutex ) 
00302                 { mutex.enterMutex(); }
00306         // this should be not-virtual
00307         ~MutexLock()
00308                 { mutex.leaveMutex(); }
00309 };
00310 
00319 class __EXPORT ThreadLock
00320 {
00321 private:
00322 #ifdef HAVE_PTHREAD_RWLOCK
00323         pthread_rwlock_t _lock;
00324 #else
00325         Mutex mutex;
00326 #endif
00327 
00328 public:
00332         ThreadLock();
00333 
00337         virtual ~ThreadLock();
00338 
00342         void readLock(void);
00343 
00347         void writeLock(void);
00348 
00354         bool tryReadLock(void);
00355 
00361         bool tryWriteLock(void);
00362 
00366         void unlock(void);
00367 };
00368 
00389 class __EXPORT ReadLock
00390 {
00391 private:
00392         ThreadLock& tl;
00393 
00394 public:
00398         ReadLock( ThreadLock& _tl ) : tl( _tl ) 
00399                 { tl.readLock(); }
00403         // this should be not-virtual
00404         ~ReadLock()
00405                 { tl.unlock(); }
00406 };
00407 
00428 class __EXPORT WriteLock
00429 {
00430 private:
00431         ThreadLock& tl;
00432 
00433 public:
00437         WriteLock( ThreadLock& _tl ) : tl( _tl ) 
00438                 { tl.writeLock(); }
00442         // this should be not-virtual
00443         ~WriteLock()
00444                 { tl.unlock(); }
00445 };
00446 
00447 
00457 class __EXPORT MutexCounter : public Mutex
00458 {
00459 private:
00460         volatile int    counter;
00461 
00462 public:
00463         MutexCounter(const char *id = NULL);
00464         MutexCounter(int initial, const char *id = NULL);
00465 
00466         friend __EXPORT int operator++(MutexCounter &mc);
00467         friend __EXPORT int operator--(MutexCounter &mc);
00468 };
00469 
00480 class __EXPORT AtomicCounter
00481 {
00482 #ifndef CCXX_USE_WIN32_ATOMIC
00483 private:
00484 #ifdef  HAVE_ATOMIC_AIX
00485         volatile int counter;
00486 #elif   HAVE_ATOMIC
00487         atomic_t atomic;
00488 #else
00489         volatile int counter;
00490         pthread_mutex_t _mutex;
00491 #endif
00492 
00493 public:
00497         AtomicCounter();
00498 
00504         AtomicCounter(int value);
00505 
00506         ~AtomicCounter();
00507 
00508         int operator++(void);
00509         int operator--(void);
00510         int operator+=(int change);
00511         int operator-=(int change);
00512         int operator+(int change);
00513         int operator-(int change);
00514         int operator=(int value);
00515         bool operator!(void);
00516         operator int();
00517 #else
00518 private:
00519         long atomic;
00520 
00521 public:
00522         inline AtomicCounter()
00523                 {atomic = 0;};
00524 
00525         inline AtomicCounter(int value)
00526                 {atomic = value;};
00527 
00528         inline int operator++(void)
00529                 {return InterlockedIncrement(&atomic);};
00530 
00531         inline int operator--(void)
00532                 {return InterlockedDecrement(&atomic);};
00533 
00534         int operator+=(int change);
00535 
00536         int operator-=(int change);
00537 
00538         inline int operator+(int change)
00539                 {return atomic + change;};
00540 
00541         inline int operator-(int change)
00542                 {return atomic - change;};
00543         
00544         inline int operator=(int value)
00545                 {return InterlockedExchange(&atomic, value);};
00546 
00547         inline bool operator!(void)
00548                 {return (atomic == 0) ? true : false;};
00549 
00550         inline operator int()
00551                 {return atomic;};
00552 #endif
00553 };
00554 
00555 #ifndef WIN32
00556 
00576 class __EXPORT Conditional 
00577 {
00578 private:
00579         pthread_cond_t _cond;
00580         pthread_mutex_t _mutex;
00581 
00582 public:
00586         Conditional(const char *id = NULL);
00587 
00591         virtual ~Conditional();
00592 
00598         void signal(bool broadcast);
00599 
00606         bool wait(timeout_t timer = 0, bool locked = false);
00607 
00614         void enterMutex(void);
00615 
00624         inline void lock(void)
00625                 {enterMutex();};
00626 
00637         bool tryEnterMutex(void);
00638 
00639         inline bool test(void)
00640                 {return tryEnterMutex();};
00641 
00647         void leaveMutex(void);
00648 
00649         inline void unlock(void)
00650                 {return leaveMutex();};
00651 };
00652 #endif
00653 
00671 class __EXPORT Semaphore
00672 {
00673 private:
00674 #ifndef WIN32
00675         unsigned _count, _waiters;
00676         pthread_mutex_t _mutex;
00677         pthread_cond_t _cond;
00678 #else
00679         HANDLE  semObject;
00680 #endif // !WIN32
00681 
00682 public:
00691         Semaphore(unsigned resource = 0);
00692 
00699         virtual ~Semaphore();
00700 
00716         bool wait(timeout_t timeout = 0);
00717 
00729         void post(void);
00730 
00731         // FIXME: how implement getValue for posix compatibility ?
00737 #ifndef WIN32
00738 #ifndef __CYGWIN32__
00739         int getValue(void);
00740 #endif
00741 #endif
00742 };
00743 
00763 class __EXPORT SemaphoreLock
00764 {
00765 private:
00766         Semaphore& sem;
00767 
00768 public:
00772         SemaphoreLock( Semaphore& _sem ) : sem( _sem ) 
00773                 { sem.wait(); }
00777         // this should be not-virtual
00778         ~SemaphoreLock()
00779                 { sem.post(); }
00780 };
00781 
00795 class __EXPORT Event
00796 {
00797 private:
00798 #ifndef WIN32
00799         pthread_mutex_t _mutex;
00800         pthread_cond_t _cond;
00801         bool _signaled;
00802         int _count;
00803 #else
00804         HANDLE cond;
00805 #endif
00806 
00807 public:
00808         Event();
00809 
00810         virtual ~Event();
00811 
00818         void reset(void);
00819 
00823         void signal(void);
00824 
00833         bool wait(timeout_t timer);
00834         bool wait(void);
00835 };
00836 
00837 
01019 class __EXPORT Thread
01020 {
01021 public:
01025         typedef enum Throw {
01026                 throwNothing,  
01027                 throwObject,   
01028                 throwException 
01029         } Throw;
01030         
01034         typedef enum Cancel
01035         {
01036                 cancelInitial=0,  
01037                 cancelDeferred=1, 
01038                 cancelImmediate,  
01039                 cancelDisabled,   
01040                 cancelManual,     
01042                 cancelDefault=cancelDeferred
01044         } Cancel;
01045 
01049         typedef enum Suspend
01050         {
01051                 suspendEnable, 
01052                 suspendDisable 
01053         } Suspend;
01054 
01055 #ifndef WIN32
01056 
01057 friend class PosixThread;
01058 #endif
01059 
01060 friend class DummyThread;
01061 private:
01062         friend class Cancellation;
01063         friend class postream_type;
01064         friend class Slog;
01065 
01066         Semaphore joinSem;
01067         static Thread* _main;
01068 
01069         Thread *_parent;
01070         Cancel _cancel;
01071         Semaphore *_start;
01072 
01073         // private data
01074         friend class ThreadImpl;
01075         class ThreadImpl* priv;
01076 
01077 public:
01078         static Thread *get(void);
01079 
01080 private:
01081 #ifdef  WIN32
01082         static unsigned __stdcall Execute(Thread *th);
01083 #endif
01084 
01085         // close current thread, free all and call Notify
01086         void close();
01087 
01088 private:
01089         char _name[32];
01090         static size_t _autostack;
01091 
01092 #ifdef WIN32
01093         DWORD waitHandle(HANDLE obj, timeout_t timeout);
01094 #endif
01095 
01096 protected:
01104         void setName(const char *text);
01105 
01115         virtual void run(void) = 0;
01116 
01138         virtual void final(void);
01139 
01151         virtual void initial(void);
01152 
01162         virtual void* getExtended(void);
01163 
01171         virtual void notify(Thread*);
01172 
01178         void exit(void);
01179 
01183         void sync(void);
01184 
01188         bool testCancel(void);
01189 
01199         void setCancel(Cancel mode);
01200 
01208         void setSuspend(Suspend mode);
01209 
01218         void terminate(void);
01219 
01223         inline void clrParent(void)
01224                 {_parent = NULL;};
01225 
01226 public:
01235         Thread(bool isMain);
01236 
01248         Thread(int pri = 0, size_t stack = 0);
01249 
01250 #ifndef WIN32
01251 
01259         Thread(const Thread &th);
01260 #endif
01261 
01268         virtual ~Thread();
01269 
01275         static void setStack(size_t size = 0)
01276                 {_autostack = size;};
01277 
01287         static void sleep(timeout_t msec);
01288 
01293         static void yield(void);
01294 
01307         int start(Semaphore *start = 0);
01308 
01317         int detach(Semaphore *start = 0);
01318 
01325         inline Thread *getParent(void)
01326                 {return _parent;};
01327 
01334         void suspend(void);
01335 
01339         void resume(void);
01340 
01347         inline Cancel getCancel(void)
01348                 {return _cancel;};
01349 
01356         bool isRunning(void);
01357 
01363         bool isDetached(void);
01364 
01368         void join(void);
01369 
01376         bool isThread(void);
01377 
01383         cctid_t getId(void) const;
01384 
01391         const char *getName(void)
01392                 {return _name;};
01393 
01399         static Throw getException(void);
01400 
01406         static void setException(Throw mode);
01407 
01414         friend inline void operator++(Thread &th)
01415                 {if (th._start) th._start->post();};
01416 
01417         friend inline void operator--(Thread &th)
01418                 {if (th._start) th._start->wait();};
01419 
01420 #ifdef WIN32
01421         bool isCancelled();
01422 
01423         static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01424 #endif
01425 
01433         static Cancel enterCancel(void);
01434 
01440         static void exitCancel(Cancel cancel);
01441 };
01442 
01452 class __EXPORT Cancellation
01453 {
01454 private:
01455         Thread::Cancel prior;
01456 
01457 public:
01458         Cancellation(Thread::Cancel cancel);
01459         ~Cancellation();
01460 };
01461 
01462 #if !defined(WIN32) && !defined(__MINGW32__)
01463 typedef int             signo_t;
01464 
01465 class PosixThread: public Thread
01466 {
01467 private:
01468 #ifndef WIN32
01469 
01470         friend class ThreadImpl;
01471         friend class Thread;
01472 #endif
01473 #ifndef CCXX_SIG_THREAD_ALARM
01474         static PosixThread *_timer;
01475         static Mutex _arm;
01476 #endif
01477         
01478         time_t  _alarm;
01479         static void signalThread(Thread* th,signo_t signo);
01480 protected:
01481                 
01488         inline void signalParent(signo_t signo)
01489                 { signalThread(_parent,signo); };
01490         
01497         inline void signalMain(signo_t signo)
01498                 { signalThread(_main,signo);};
01499 
01504         virtual void onTimer(void);
01505 
01510         virtual void onHangup(void);
01511 
01516         virtual void onException(void);
01517 
01522         virtual void onDisconnect(void);
01523 
01528         virtual void onPolling(void);
01529 
01536         virtual void onSignal(int);
01537         
01550         void setTimer(timeout_t timer, bool periodic = false);
01551         
01558         timeout_t getTimer(void) const;
01559         
01565         void endTimer(void);
01566 
01567 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)     
01568 
01574         void waitSignal(signo_t signo);
01575 #endif
01576         
01583         void setSignal(int signo, bool active);
01584 
01591         pthread_attr_t *getPthreadAttrPtr(void);
01592 
01597         pthread_t getPthreadId(void);
01598 
01599 public:
01600 
01601         PosixThread(int pri = 0, size_t stack = 0);
01602         
01608         inline void signalThread(int signo)
01609                 {signalThread(this, signo);};
01610 
01617         static void sigInstall(int signo);
01618 };
01619 #endif
01620 
01635 class __EXPORT ThreadKey
01636 {
01637 private:
01638 #ifndef WIN32
01639         pthread_key_t key;
01640         typedef void (*TDestruct)(void*);
01641         friend class ThreadImpl;
01642         ThreadKey(TDestruct destruct);
01643 #else
01644         DWORD   key;
01645 #endif
01646 
01647 public:
01651         ThreadKey();
01652 
01656         virtual ~ThreadKey();
01657 
01665         void *getKey(void);
01666 
01674         void setKey(void *);
01675 };
01676 
01687 class __EXPORT TimerPort
01688 {
01689 #ifndef WIN32
01690         struct timeval timer;
01691 #else
01692         DWORD timer;
01693 #endif
01694         bool active;
01695 
01696 public:
01703         TimerPort();
01704 
01713         void setTimer(timeout_t timeout = 0);
01714 
01724         void incTimer(timeout_t timeout);
01725 
01731         void endTimer(void);
01732 
01744         timeout_t getTimer(void) const;
01745 
01755         timeout_t getElapsed(void) const;
01756 };
01757 
01758 
01759 
01760 // FIXME: not in win32 implementation
01761 #if !defined(WIN32)
01762 
01763 // FIXME: private declaration ???
01764 struct  timespec *getTimeout(struct timespec *spec, timeout_t timeout); 
01765 
01766 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01767 void    wait(signo_t signo);
01768 #endif
01769 
01770 #endif // !WIN32
01771 
01772 #ifdef USE_POLL
01773 
01781 class Poller 
01782 {
01783 private:
01784         int nufds;
01785         pollfd *ufds;
01786 
01787 public:
01788         Poller();
01789 
01790         virtual ~Poller();
01791 
01799         pollfd *getList(int cnt);
01800 
01806         inline  pollfd *getList(void)
01807                 {return ufds;};
01808 };
01809 #endif
01810 
01811 inline Thread *getThread(void)
01812         {return Thread::get();}
01813 
01843 class __EXPORT SysTime
01844 {
01845 private:
01846                 static Mutex timeLock;
01847 
01848 protected:
01849                 inline static void lock(void)
01850                         {timeLock.enterMutex();}
01851 
01852                 inline static void unlock(void)
01853                         {timeLock.leaveMutex();}
01854 
01855 public:
01856         static time_t getTime(time_t *tloc = NULL);
01857         static time_t time(time_t *tloc) 
01858                         { return getTime(tloc); };
01859 
01860         static int getTimeOfDay(struct timeval *tp);
01861         static int gettimeofday(struct timeval *tp, struct timezone *)
01862                         { return getTimeOfDay(tp); };
01863         
01864         static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01865         static struct tm *locatime(const time_t *clock, struct tm *result)
01866                         { return getLocalTime(clock, result); };
01867 
01868                 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01869                 static struct tm *gmtime(const time_t *clock, struct tm *result)
01870                         { return getGMTTime(clock, result);};
01871 }; 
01872 
01873 #ifndef HAVE_LOCALTIME_R
01874 
01875 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01876         {return SysTime::getLocalTime(t, b);};
01877 inline char *ctime_r(const time_t *t, char *buf)
01878         {return ctime(t);};
01879 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01880 {return SysTime::getGMTTime(t, b);};
01881 inline char *asctime_r(const struct tm *tm, char *b) \
01882         {return asctime(tm);};
01883 
01884 #endif 
01885         
01886 #ifdef  CCXX_NAMESPACES
01887 }
01888 #endif
01889 
01890 #endif
01891 

Generated on Tue Sep 13 02:19:09 2005 for Bayonne by  doxygen 1.4.4