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

thread.h

Go to the documentation of this file.
00001 // Copyright (C) 1999-2003 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 to the GNU General Public License, permission is 
00018 // granted for additional uses of the text contained in its release 
00019 // of Common C++.
00020 // 
00021 // The exception is that, if you link the Common C++ library with other
00022 // files to produce an executable, this does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public License.
00024 // Your use of that executable is in no way restricted on account of
00025 // linking the Common C++ library code into it.
00026 //
00027 // This exception does not however invalidate any other reasons why
00028 // the executable file might be covered by the GNU General Public License.
00029 // 
00030 // This exception applies only to the code released under the 
00031 // name Common C++.  If you copy code from other releases into a copy of
00032 // Common C++, as the General Public License permits, the exception does
00033 // not apply to the code that you add in this way.  To avoid misleading
00034 // anyone as to the status of such modified files, you must delete
00035 // this exception notice from them.
00036 // 
00037 // If you write modifications of your own for Common C++, it is your choice
00038 // whether to permit this exception to apply to your modifications.
00039 // If you do not wish that, delete this exception notice.
00040 
00046 #ifndef CCXX_THREAD_H_
00047 #define CCXX_THREAD_H_
00048 
00049 #ifndef WIN32
00050 #define CCXX_POSIX
00051 #endif // !WIN32
00052 
00053 #ifndef CCXX_CONFIG_H_
00054 #include <cc++/config.h>
00055 #endif
00056 
00057 #ifndef WIN32
00058 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00059 #define CCXX_SYSV_SEMAPHORES
00060 #endif
00061 
00062 #ifdef  MACOSX
00063 #define CCXX_NAMED_SEMAPHORES
00064 #define CCXX_BROKEN_SEMGETVALUE
00065 #endif
00066 
00067 #ifndef HAVE_PTHREAD_H
00068 #include <pthread.h>
00069 #ifndef CCXX_SYSV_SEMAPHORES
00070 #include <semaphore.h>
00071 #endif
00072 #endif
00073 #endif // !WIN32
00074 
00075 #undef CCXX_USE_WIN32_ATOMIC
00076 #ifndef WIN32
00077 #include <time.h>
00078 #include <signal.h>
00079 #include <unistd.h>
00080 
00081 #ifdef  _THR_UNIXWARE
00082 #undef  PTHREAD_MUTEXTYPE_RECURSIVE
00083 #endif
00084 
00085 typedef pthread_t       cctid_t;
00086 typedef unsigned long   timeout_t;
00087 
00088 /*
00089 #if defined(__CYGWIN32__)
00090 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00091 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00092 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00093 #define CCXX_USE_WIN32_ATOMIC 1
00094 #endif
00095 */
00096 
00097 #else // WIN32
00098 typedef DWORD   cctid_t;
00099 typedef DWORD   timeout_t;
00100 
00101 #define MAX_SEM_VALUE   1000000
00102 #define CCXX_USE_WIN32_ATOMIC 1
00103 #if defined(__CYGWIN32__) 
00104 //#include <Windows32/CommonFunctions.h>
00105 #else
00106 #if _MSC_VER < 1300
00107 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00108 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00109 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00110 #endif
00111 #endif
00112 
00113 #endif // !WIN32
00114 
00115 #ifdef  CCXX_NAMESPACES
00116 namespace ost {
00117 #endif
00118 
00119 class __EXPORT Thread;
00120 class __EXPORT ThreadKey;
00121 
00122 #define TIMEOUT_INF ~((timeout_t) 0)
00123 
00124 #define ENTER_CRITICAL  enterMutex();
00125 #define LEAVE_CRITICAL  leaveMutex();
00126 #define ENTER_DEFERRED  setCancel(cancelDeferred);
00127 #define LEAVE_DEFERRED  setCancel(cancelImmediate);
00128 
00129 #ifndef WIN32
00130 // These macros override common functions with thread-safe versions. In
00131 // particular the common "libc" sleep() has problems since it normally
00132 // uses SIGARLM (as actually defined by "posix").  The pthread_delay and
00133 // usleep found in libpthread are gaurenteed not to use SIGALRM and offer
00134 // higher resolution.  psleep() is defined to call the old process sleep.
00135 
00136 #undef  sleep
00137 #define psleep(x)       (sleep)(x)
00138 
00139 #endif // !WIN32
00140 
00141 #undef Yield
00142 
00143 class __EXPORT Conditional;
00144 class __EXPORT Event;
00145 
00189 class __EXPORT Mutex
00190 {
00191         friend class Conditional;
00192         friend class Event;
00193 private:
00194         static bool _debug;
00195         const char *_name;
00196 #ifndef WIN32
00197 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00198         volatile int _level;
00199         volatile Thread *_tid;
00200 #endif
00201         /*
00202          * Pthread mutex object.  This is protected rather than private
00203          * because some mixed mode pthread operations require a mutex as
00204          * well as their primary pthread object.  A good example of this
00205          * is the Event class, as waiting on a conditional object must be
00206          * associated with an accessable mutex.  An alternative would be
00207          * to make such classes "friend" classes of the Mutex.
00208          */
00209         pthread_mutex_t _mutex;
00210 #else
00211         HANDLE mutex;
00212 #endif
00213 
00214 public:
00218         Mutex(const char *name = NULL);
00219 
00225         virtual ~Mutex();
00226 
00232         static void setDebug(bool mode)
00233                 {_debug = mode;};
00234 
00242         void enterMutex(void);
00243 
00254         bool tryEnterMutex(void);
00255 
00266         void leaveMutex(void);
00267 };
00268 
00292 class __EXPORT MutexLock
00293 {
00294 private:
00295         Mutex& mutex;
00296 public:
00300         MutexLock( Mutex& _mutex ) : mutex( _mutex ) 
00301                 { mutex.enterMutex(); }
00305         // this should be not-virtual
00306         ~MutexLock()
00307                 { mutex.leaveMutex(); }
00308 };
00309 
00318 class __EXPORT ThreadLock
00319 {
00320 private:
00321 #ifdef HAVE_PTHREAD_RWLOCK
00322         pthread_rwlock_t _lock;
00323 #else
00324         Mutex mutex;
00325 #endif
00326 
00327 public:
00331         ThreadLock();
00332 
00336         virtual ~ThreadLock();
00337 
00341         void readLock(void);
00342 
00346         void writeLock(void);
00347 
00353         bool tryReadLock(void);
00354 
00360         bool tryWriteLock(void);
00361 
00365         void unlock(void);
00366 };
00367 
00377 class __EXPORT MutexCounter : public Mutex
00378 {
00379 private:
00380         int     counter;
00381 
00382 public:
00383         MutexCounter(const char *id = NULL);
00384         MutexCounter(int initial, const char *id = NULL);
00385 
00386         friend __EXPORT int operator++(MutexCounter &mc);
00387         friend __EXPORT int operator--(MutexCounter &mc);
00388 };
00389 
00400 class __EXPORT AtomicCounter
00401 {
00402 #ifndef CCXX_USE_WIN32_ATOMIC
00403 private:
00404 #ifdef  HAVE_ATOMIC
00405         atomic_t atomic;
00406 #else
00407         int counter;
00408         Mutex lock;
00409 #endif
00410 
00411 public:
00415         AtomicCounter();
00416 
00422         AtomicCounter(int value);
00423 
00424         int operator++(void);
00425         int operator--(void);
00426         int operator+=(int change);
00427         int operator-=(int change);
00428         int operator+(int change);
00429         int operator-(int change);
00430         int operator=(int value);
00431         bool operator!(void);
00432         operator int();
00433 #else
00434 private:
00435         long atomic;
00436 
00437 public:
00438         inline AtomicCounter()
00439                 {atomic = 0;};
00440 
00441         inline AtomicCounter(int value)
00442                 {atomic = value;};
00443 
00444         inline int operator++(void)
00445                 {return InterlockedIncrement(&atomic);};
00446 
00447         inline int operator--(void)
00448                 {return InterlockedDecrement(&atomic);};
00449 
00450         int operator+=(int change);
00451 
00452         int operator-=(int change);
00453 
00454         inline int operator+(int change)
00455                 {return atomic + change;};
00456 
00457         inline int operator-(int change)
00458                 {return atomic - change;};
00459         
00460         inline int operator=(int value)
00461                 {return InterlockedExchange(&atomic, value);};
00462 
00463         inline bool operator!(void)
00464                 {return (atomic == 0) ? true : false;};
00465 
00466         inline operator int()
00467                 {return atomic;};
00468 #endif
00469 };
00470 
00471 #ifndef WIN32
00472 
00492 class __EXPORT Conditional : public Mutex
00493 {
00494 private:
00495         pthread_cond_t _cond;
00496 
00497 public:
00501         Conditional(const char *id = NULL);
00502 
00506         virtual ~Conditional();
00507 
00513         void signal(bool broadcast);
00514 
00521         bool wait(timeout_t timer = 0, bool locked = false);
00522 
00523 };
00524 #endif
00525 
00543 class __EXPORT Semaphore
00544 {
00545 private:
00546 #ifndef WIN32
00547 #ifdef  CCXX_SYSV_SEMAPHORES
00548         int _semaphore;
00549 #else
00550         sem_t _semaphore;
00551         sem_t *_semobject;
00552 #endif
00553 #else // WIN32
00554         HANDLE  semObject;
00555 #endif // !WIN32
00556 
00557 public:
00566         Semaphore(size_t resource = 0);
00567 
00574         virtual ~Semaphore();
00575 
00589         void wait(void);
00590 
00602         bool tryWait(void);
00603 
00615         void post(void);
00616 
00617         // FIXME: how implement getValue for posix compatibility ?
00623 #ifndef WIN32
00624 #ifndef __CYGWIN32__
00625         int getValue(void);
00626 #endif
00627 #endif
00628 };
00629 
00643 class __EXPORT Event
00644 {
00645 private:
00646 #ifndef WIN32
00647         Mutex mutex;
00648         pthread_cond_t _cond;
00649         bool _signaled;
00650         int _count;
00651 #else
00652         HANDLE cond;
00653 #endif
00654 
00655 public:
00656         Event();
00657 
00658         virtual ~Event();
00659 
00666         void reset(void);
00667 
00671         void signal(void);
00672 
00681         bool wait(timeout_t timer);
00682         bool wait(void);
00683 };
00684 
00685 
00867 class __EXPORT Thread
00868 {
00869 public:
00873         typedef enum Throw {
00874                 throwNothing,  
00875                 throwObject,   
00876                 throwException 
00877         } Throw;
00878         
00882         typedef enum Cancel
00883         {
00884                 cancelInitial=0,  
00885                 cancelDeferred=1, 
00886                 cancelImmediate,  
00887                 cancelDisabled,   
00888                 cancelManual,     
00890                 cancelDefault=cancelDeferred
00892         } Cancel;
00893 
00897         typedef enum Suspend
00898         {
00899                 suspendEnable, 
00900                 suspendDisable 
00901         } Suspend;
00902 
00903 #ifndef WIN32
00904 
00905 friend class PosixThread;
00906 #endif
00907 
00908 friend class DummyThread;
00909 private:
00910         friend class postream_type;
00911         friend class Slog;
00912 
00913         Semaphore joinSem;
00914         static Thread* _main;
00915 
00916         Thread *_parent;
00917         enum Cancel _cancel;
00918         Semaphore *_start;
00919 
00920         // private data
00921         friend class ThreadImpl;
00922         class ThreadImpl* priv;
00923 
00924 public:
00925         static Thread *getThread(void);
00926         friend inline Thread *getThread() {return Thread::getThread();};
00927 
00928 private:
00929 #ifdef  WIN32
00930         static unsigned __stdcall Execute(Thread *th);
00931 #endif
00932 
00933         // close current thread, free all and call Notify
00934         void close();
00935 
00936 private:
00937         char _name[32];
00938         static size_t _autostack;
00939 
00940 #ifdef WIN32
00941         DWORD waitHandle(HANDLE obj, timeout_t timeout);
00942 #endif
00943 
00944 protected:
00952         void setName(const char *text);
00953 
00963         virtual void run(void) = 0;
00964 
00986         virtual void final(void)
00987                 {return;};
00988 
01000         virtual void initial(void)
01001                 {return;};
01002 
01012         virtual void* getExtended(void)
01013                 {return NULL;};
01014 
01022         virtual void notify(Thread*)
01023                 {return;};
01024 
01030         void exit(void);
01031 
01035         bool testCancel(void);
01036 
01046         void setCancel(Cancel mode);
01047 
01055         void setSuspend(Suspend mode);
01056 
01065         void terminate(void);
01066 
01070         inline void clrParent(void)
01071                 {_parent = NULL;};
01072 
01073 public:
01082         Thread(bool isMain);
01083 
01095         Thread(int pri = 0, size_t stack = 0);
01096 
01097 #ifndef WIN32
01098 
01106         Thread(const Thread &th);
01107 #endif
01108 
01115         virtual ~Thread();
01116 
01122         static void setStack(size_t size = 0)
01123                 {_autostack = size;};
01124 
01134         static void sleep(timeout_t msec);
01135 
01140         static void yield(void);
01141 
01154         int start(Semaphore *start = 0);
01155 
01164         int detach(Semaphore *start = 0);
01165 
01172         inline Thread *getParent(void)
01173                 {return _parent;};
01174 
01181         void suspend(void);
01182 
01186         void resume(void);
01187 
01194         inline Cancel getCancel(void)
01195                 {return _cancel;};
01196 
01203         bool isRunning(void);
01204 
01210         bool isDetached(void);
01211 
01215         void join(void);
01216 
01223         bool isThread(void);
01224 
01230         cctid_t getThreadId(void) const;
01231 
01238         const char *getThreadName(void)
01239                 {return _name;};
01240 
01246         static Throw getException(void);
01247 
01253         static void setException(Throw mode);
01254 
01261         friend inline void operator++(Thread &th)
01262                 {if (th._start) th._start->post();};
01263 
01264         friend inline void operator--(Thread &th)
01265                 {if (th._start) th._start->wait();};
01266 
01267 #ifdef WIN32
01268         bool isCancelled();
01269 
01270         static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01271 #endif
01272 };
01273 
01274 #if !defined(WIN32) && !defined(__MINGW32__)
01275 typedef int             signo_t;
01276 
01277 class PosixThread: public Thread
01278 {
01279 private:
01280 #ifndef WIN32
01281 
01282         friend class ThreadImpl;
01283         friend class Thread;
01284 #endif
01285 #ifndef CCXX_SIG_THREAD_ALARM
01286         static PosixThread *_timer;
01287         static Mutex _arm;
01288 #endif
01289         
01290         time_t  _alarm;
01291         static void signalThread(Thread* th,signo_t signo);
01292 protected:
01293                 
01300         inline void signalParent(signo_t signo)
01301                 { signalThread(_parent,signo); };
01302         
01309         inline void signalMain(signo_t signo)
01310                 { signalThread(_main,signo);};
01311 
01316         virtual void onTimer(void)
01317                 {return;};
01318 
01323         virtual void onHangup(void)
01324                 {return;};
01325 
01330         virtual void onException(void)
01331                 {return;};
01332 
01337         virtual void onDisconnect(void)
01338                 {return;};
01339 
01344         virtual void onPolling(void)
01345                 {return;};
01346 
01353         virtual void onSignal(int)
01354                 {return;};
01355         
01368         void setTimer(timeout_t timer, bool periodic = false);
01369         
01376         timeout_t getTimer(void) const;
01377         
01383         void endTimer(void);
01384         
01391         void waitSignal(signo_t signo);
01392         
01399         void setSignal(int signo, bool active);
01400 public:
01401 
01402         PosixThread(int pri = 0, size_t stack = 0);
01403         
01409         inline void signalThread(int signo)
01410                 {signalThread(this, signo);};
01411 
01418         static void sigInstall(int signo);
01419 };
01420 #endif
01421 
01436 class __EXPORT ThreadKey
01437 {
01438 private:
01439 #ifndef WIN32
01440         pthread_key_t key;
01441         typedef void (*TDestruct)(void*);
01442         friend class ThreadImpl;
01443         ThreadKey(TDestruct destruct);
01444 #else
01445         DWORD   key;
01446 #endif
01447 
01448 public:
01452         ThreadKey();
01456         virtual ~ThreadKey();
01464         void *getKey(void);
01472         void setKey(void *);
01473 };
01474 
01485 class __EXPORT TimerPort
01486 {
01487 #ifndef WIN32
01488         struct timeval timer;
01489 #else
01490         DWORD timer;
01491 #endif
01492         bool active;
01493 
01494 public:
01501         TimerPort();
01502 
01511         void setTimer(timeout_t timeout = 0);
01512 
01522         void incTimer(timeout_t timeout);
01523 
01529         void endTimer(void);
01530 
01542         timeout_t getTimer(void) const;
01543 
01553         timeout_t getElapsed(void) const;
01554 };
01555 
01556 
01557 
01558 // FIXME: not in win32 implementation
01559 #if !defined(WIN32)
01560 
01561 // FIXME: private declaration ???
01562 struct  timespec *getTimeout(struct timespec *spec, timeout_t timeout); 
01563 
01564 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01565 void    wait(signo_t signo);
01566 #endif
01567 
01568 #endif // !WIN32
01569 
01570 #ifdef USE_POLL
01571 
01579 class Poller 
01580 {
01581 private:
01582         int nufds;
01583         pollfd *ufds;
01584 
01585 public:
01586         Poller();
01587 
01588         virtual ~Poller();
01589 
01597         pollfd *getList(int cnt);
01598 
01604         inline  pollfd *getList(void)
01605                 {return ufds;};
01606 };
01607 #endif
01608 
01609 #ifdef  CCXX_NAMESPACES
01610 };
01611 #endif
01612 
01613 #endif
01614 

Generated on Fri Feb 27 11:37:10 2004 for GNU CommonC++ by doxygen 1.3.5