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

thread.h

Go to the documentation of this file.
00001 // Copyright (C) 1999-2002 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 CCXX_EXCEPTION_H_
00058 #include <cc++/exception.h>
00059 #endif
00060 
00061 #ifndef WIN32
00062 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00063 #define CCXX_SYSV_SEMAPHORES
00064 #endif
00065 
00066 #ifndef HAVE_PTHREAD_H
00067 #include <pthread.h>
00068 #ifndef CCXX_SYSV_SEMAPHORES
00069 #include <semaphore.h>
00070 #endif
00071 #endif
00072 #endif // !WIN32
00073 
00074 #undef CCXX_USE_WIN32_ATOMIC
00075 #ifndef WIN32
00076 #include <time.h>
00077 #include <signal.h>
00078 #include <unistd.h>
00079 
00080 #ifdef  _THR_UNIXWARE
00081 #undef  PTHREAD_MUTEXTYPE_RECURSIVE
00082 #endif
00083 
00084 typedef pthread_t       cctid_t;
00085 typedef unsigned long   timeout_t;
00086 
00087 /*
00088 #if defined(__CYGWIN32__) 
00089 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00090 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00091 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00092 #define CCXX_USE_WIN32_ATOMIC 1
00093 #endif
00094 */
00095 
00096 #else // WIN32
00097 typedef DWORD   cctid_t;
00098 typedef DWORD   timeout_t;
00099 
00100 #define MAX_SEM_VALUE   1000000
00101 #define CCXX_USE_WIN32_ATOMIC 1
00102 #if defined(__CYGWIN32__) 
00103 //#include <Windows32/CommonFunctions.h>
00104 #else
00105 #if _MSC_VER < 1300
00106 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00107 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00108 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00109 #endif
00110 #endif
00111 
00112 #endif // !WIN32
00113 
00114 #ifdef  CCXX_NAMESPACES
00115 namespace ost {
00116 #endif
00117 
00118 class CCXX_CLASS_EXPORT Thread;
00119 class CCXX_CLASS_EXPORT ThreadKey;
00120 
00121 #define TIMEOUT_INF ~((timeout_t) 0)
00122 
00123 #define ENTER_CRITICAL  enterMutex();
00124 #define LEAVE_CRITICAL  leaveMutex();
00125 #define ENTER_DEFERRED  setCancel(cancelDeferred);
00126 #define LEAVE_DEFERRED  setCancel(cancelImmediate);
00127 
00128 #ifndef WIN32
00129 // These macros override common functions with thread-safe versions. In
00130 // particular the common "libc" sleep() has problems since it normally
00131 // uses SIGARLM (as actually defined by "posix").  The pthread_delay and
00132 // usleep found in libpthread are gaurenteed not to use SIGALRM and offer
00133 // higher resolution.  psleep() is defined to call the old process sleep.
00134 
00135 #undef  sleep
00136 #define psleep(x)       (sleep)(x)
00137 
00138 #endif // !WIN32
00139 
00140 #undef Yield
00141 
00142 #ifdef WIN32
00143 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00144 #endif
00145 
00146 class Conditional;
00147 class CCXX_CLASS_EXPORT Event;
00148 
00192 class CCXX_CLASS_EXPORT Mutex
00193 {
00194         friend class Conditional;
00195         friend class Event;
00196 private:
00197 #ifndef WIN32
00198 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00199         volatile int _level;
00200         volatile Thread *_tid;
00201 #endif
00202         /*
00203          * Pthread mutex object.  This is protected rather than private
00204          * because some mixed mode pthread operations require a mutex as
00205          * well as their primary pthread object.  A good example of this
00206          * is the Event class, as waiting on a conditional object must be
00207          * associated with an accessable mutex.  An alternative would be
00208          * to make such classes "friend" classes of the Mutex.
00209          */
00210         pthread_mutex_t _mutex;
00211 #else
00212         HANDLE mutex;
00213 #endif
00214 
00215 public:
00219         Mutex();
00220 
00226         virtual ~Mutex();
00227 
00235         void enterMutex(void);
00236 
00247         bool tryEnterMutex(void);
00248 
00259         void leaveMutex(void);
00260 };
00261 
00283 class MutexLock
00284 {
00285 private:
00286         Mutex& mutex;
00287 public:
00291         MutexLock( Mutex& _mutex ) : mutex( _mutex ) 
00292                 { mutex.enterMutex(); }
00296         // this should be not-virtual
00297         ~MutexLock()
00298                 { mutex.leaveMutex(); }
00299 };
00300 
00309 class CCXX_CLASS_EXPORT ThreadLock
00310 {
00311 private:
00312 #ifdef HAVE_PTHREAD_RWLOCK
00313         pthread_rwlock_t _lock;
00314 #else
00315         Mutex mutex;
00316 #endif
00317 
00318 public:
00322         ThreadLock();
00323 
00327         virtual ~ThreadLock();
00328 
00332         void readLock(void);
00333 
00337         void writeLock(void);
00338 
00344         bool tryReadLock(void);
00345 
00351         bool tryWriteLock(void);
00352 
00356         void unlock(void);
00357 };
00358 
00368 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00369 {
00370 private:
00371         int     counter;
00372 
00373 public:
00374         MutexCounter();
00375         MutexCounter(int initial);
00376 
00377         friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00378         friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00379 };
00380 
00391 class CCXX_CLASS_EXPORT AtomicCounter
00392 {
00393 #ifndef CCXX_USE_WIN32_ATOMIC
00394 private:
00395 #ifdef  HAVE_ATOMIC
00396         atomic_t atomic;
00397 #else
00398         int counter;
00399         Mutex lock;
00400 #endif
00401 
00402 public:
00406         AtomicCounter();
00407 
00413         AtomicCounter(int value);
00414 
00415         int operator++(void);
00416         int operator--(void);
00417         int operator+=(int change);
00418         int operator-=(int change);
00419         int operator+(int change);
00420         int operator-(int change);
00421         int operator=(int value);
00422         bool operator!(void);
00423         operator int();
00424 #else
00425 private:
00426         long atomic;
00427 
00428 public:
00429         inline AtomicCounter()
00430                 {atomic = 0;};
00431 
00432         inline AtomicCounter(int value)
00433                 {atomic = value;};
00434 
00435         inline int operator++(void)
00436                 {return InterlockedIncrement(&atomic);};
00437 
00438         inline int operator--(void)
00439                 {return InterlockedDecrement(&atomic);};
00440 
00441         int operator+=(int change);
00442 
00443         int operator-=(int change);
00444 
00445         inline int operator+(int change)
00446                 {return atomic + change;};
00447 
00448         inline int operator-(int change)
00449                 {return atomic - change;};
00450         
00451         inline int operator=(int value)
00452                 {return InterlockedExchange(&atomic, value);};
00453 
00454         inline bool operator!(void)
00455                 {return (atomic == 0) ? true : false;};
00456 
00457         inline operator int()
00458                 {return atomic;};
00459 #endif
00460 };
00461 
00462 #ifndef WIN32
00463 
00483 class Conditional : public Mutex
00484 {
00485 private:
00486         pthread_cond_t _cond;
00487 
00488 public:
00492         Conditional();
00493 
00497         virtual ~Conditional();
00498 
00504         void signal(bool broadcast);
00505 
00509         void wait(timeout_t timer = 0); 
00510 };
00511 #endif
00512 
00530 class CCXX_CLASS_EXPORT Semaphore
00531 {
00532 private:
00533 #ifndef WIN32
00534 #ifdef  CCXX_SYSV_SEMAPHORES
00535         int _semaphore;
00536 #else
00537         sem_t _semaphore;
00538 #endif
00539 #else // WIN32
00540         HANDLE  semObject;
00541 #endif // !WIN32
00542 
00543 public:
00552         Semaphore(size_t resource = 0);
00553 
00560         virtual ~Semaphore();
00561 
00575         void wait(void);
00576 
00588         bool tryWait(void);
00589 
00601         void post(void);
00602 
00603         // FIXME: how implement getValue for posix compatibility ?
00609 #ifndef WIN32
00610 #ifndef __CYGWIN32__
00611         int getValue(void);
00612 #endif
00613 #endif
00614 };
00615 
00629 class CCXX_CLASS_EXPORT Event
00630 {
00631 private:
00632 #ifndef WIN32
00633         Mutex mutex;
00634         pthread_cond_t _cond;
00635         bool _signaled;
00636         int _count;
00637 #else
00638         HANDLE cond;
00639 #endif
00640 
00641 public:
00642         Event();
00643 
00644         virtual ~Event();
00645 
00652         void reset(void);
00653 
00657         void signal(void);
00658 
00667         bool wait(timeout_t timer);
00668         bool wait(void);
00669 };
00670 
00692 class CCXX_CLASS_EXPORT Buffer
00693 {
00694 private:
00695         Mutex lock_head, lock_tail;
00696         Semaphore size_head, size_tail;
00697         size_t _size;
00698         size_t _used;
00699 
00700 protected:
00706         virtual int onPeek(void *buf) = 0;
00712         virtual int onWait(void *buf) = 0;
00718         virtual int onPost(void *buf) = 0;
00719 
00720 public:
00725         Buffer(size_t capacity);
00730         virtual ~Buffer()
00731                 {return;};
00732 
00737         inline size_t getSize(void)
00738                 {return _size;};
00739         
00746         inline size_t getUsed(void)
00747                 {return _used;};
00748 
00757         int wait(void *buf);
00758 
00766         int post(void *buf);
00767 
00774         int peek(void *buf);
00775 
00780         virtual bool isValid(void)
00781                 {return true;};
00782 };
00783 
00791 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00792 {
00793 private:
00794         char *buf, *head, *tail;
00795         size_t objsize;
00796 
00797 protected:
00803         int onPeek(void *buf);
00804 
00810         int onWait(void *buf);
00811 
00817         int onPost(void *buf);  
00818 
00819 public:
00827         FixedBuffer(size_t capacity, size_t objsize);
00828 
00835         FixedBuffer(const FixedBuffer &fb);
00836 
00840         virtual ~FixedBuffer();
00841 
00842         FixedBuffer &operator=(const FixedBuffer &fb);
00843 
00844         bool isValid(void);
00845 };
00846 
01026 class CCXX_CLASS_EXPORT Thread
01027 {
01028 public:
01032         typedef enum Throw {
01033                 throwNothing,  
01034                 throwObject,   
01035                 throwException 
01036         } Throw;
01037         
01041         typedef enum Cancel
01042         {
01043                 cancelInitial=0,  
01044                 cancelDeferred=1, 
01045                 cancelImmediate,  
01046                 cancelDisabled,   
01047                 cancelManual,     
01049                 cancelDefault=cancelDeferred
01051         } Cancel;
01052 
01056         typedef enum Suspend
01057         {
01058                 suspendEnable, 
01059                 suspendDisable 
01060         } Suspend;
01061 
01062 #ifndef WIN32
01063 
01064 friend class PosixThread;
01065 #endif
01066 
01067 friend class DummyThread;
01068 private:
01069         friend class Slog;
01070 
01071         static Thread* _main;
01072 
01073         Thread *_parent;
01074         enum Cancel _cancel;
01075         Semaphore *_start;
01076 
01077         // private data
01078         friend class ThreadImpl;
01079         class ThreadImpl* priv;
01080 
01081 #ifndef WIN32
01082         friend Thread *getThread(void);
01083 #else
01084         static unsigned __stdcall Execute(Thread *th);
01085 #endif
01086 
01087         // close current thread, free all and call Notify
01088         void close();
01089         
01090 protected:
01100         virtual void run(void) = 0;
01101 
01118         virtual void final(void)
01119                 {return;};
01120 
01132         virtual void initial(void)
01133                 {return;};
01134 
01144         virtual void* getExtended(void)
01145                 {return NULL;};
01146 
01154         virtual void notify(Thread*)
01155                 {return;};
01156 
01162         void exit(void);
01163 
01167         bool testCancel(void);
01168 
01178         void setCancel(Cancel mode);
01179 
01187         void setSuspend(Suspend mode);
01188 
01197         void terminate(void);
01198 
01202         inline void clrParent(void)
01203                 {_parent = NULL;};
01204 
01205 #ifdef WIN32
01206         // FIXME: should be private
01207         DWORD waitHandle(HANDLE obj, timeout_t timeout);
01208 #endif
01209 
01210 public:
01219         Thread(bool isMain);
01220 
01232         Thread(int pri = 0, size_t stack = 0);
01233 
01234 #ifndef WIN32
01235 
01243         Thread(const Thread &th);
01244 #endif
01245 
01252         virtual ~Thread();
01253 
01263         static void sleep(timeout_t msec);
01264 
01269         static void yield(void);
01270 
01283         int start(Semaphore *start = 0);
01284 
01293         int detach(Semaphore *start = 0);
01294 
01301         inline Thread *getParent(void)
01302                 {return _parent;};
01303 
01310         void suspend(void);
01311 
01315         void resume(void);
01316 
01323         inline Cancel getCancel(void)
01324                 {return _cancel;};
01325 
01332         bool isRunning(void);
01333 
01340         bool isThread(void);
01341 
01347         friend CCXX_EXPORT(Throw) getException(void);
01348 
01354         friend CCXX_EXPORT(void) setException(Throw mode);
01355 
01362         friend inline void operator++(Thread &th)
01363                 {if (th._start) th._start->post();};
01364 
01365         friend inline void operator--(Thread &th)
01366                 {if (th._start) th._start->wait();};
01367 
01368 #ifdef WIN32
01369         // FIXME: not defined in posix
01370         bool isCancelled();
01371 
01372         friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01373 #endif
01374 };
01375 
01381 CCXX_EXPORT(Thread*) getThread(void);
01383 CCXX_EXPORT(Thread::Throw) getException(void);
01385 CCXX_EXPORT(void) setException(Thread::Throw mode);
01386 
01387 #if !defined(WIN32) && !defined(__CYGWIN32__)  && !defined(__MINGW32__)
01388 typedef int             signo_t;
01389 
01390 class PosixThread: public Thread
01391 {
01392 private:
01393 #ifndef WIN32
01394 
01395         friend class ThreadImpl;
01396         friend class Thread;
01397 #endif
01398 #ifndef CCXX_SIG_THREAD_ALARM
01399         static PosixThread *_timer;
01400         static Mutex _arm;
01401 #endif
01402         
01403         time_t  _alarm;
01404         static void signalThread(Thread* th,signo_t signo);
01405 protected:
01406                 
01413         inline void signalParent(signo_t signo)
01414                 { signalThread(_parent,signo); };
01415         
01422         inline void signalMain(signo_t signo)
01423                 { signalThread(_main,signo);};
01424 
01429         virtual void onTimer(void)
01430                 {return;};
01431 
01436         virtual void onHangup(void)
01437                 {return;};
01438 
01443         virtual void onException(void)
01444                 {return;};
01445 
01450         virtual void onDisconnect(void)
01451                 {return;};
01452 
01457         virtual void onPolling(void)
01458                 {return;};
01459 
01466         virtual void onSignal(int)
01467                 {return;};
01468         
01478         void setTimer(timeout_t timer);
01479         
01486         timeout_t getTimer(void) const;
01487         
01493         void endTimer(void);
01494         
01501         void waitSignal(signo_t signo);
01502         
01509         void setSignal(int signo, bool active);
01510 public:
01511 
01512         CCXX_MEMBER_EXPORT(CCXX_EMPTY) PosixThread(int pri = 0, size_t stack = 0);
01513         
01519         inline void signalThread(int signo)
01520                 {signalThread(this, signo);};
01521 
01528         friend void sigInstall(int signo);
01529 };
01530 #endif
01531 
01546 class ThreadKey
01547 {
01548 private:
01549 #ifndef WIN32
01550         pthread_key_t key;
01551         typedef void (*TDestruct)(void*);
01552         friend class ThreadImpl;
01553         ThreadKey(TDestruct destruct);
01554 #else
01555         DWORD   key;
01556 #endif
01557 
01558 public:
01562         ThreadKey();
01566         virtual ~ThreadKey();
01574         void *getKey(void);
01582         void setKey(void *);
01583 };
01584 
01595 class CCXX_CLASS_EXPORT TimerPort
01596 {
01597 #ifndef WIN32
01598         struct timeval timer;
01599 #else
01600         DWORD timer;
01601 #endif
01602         bool active;
01603 
01604 public:
01611         TimerPort();
01612 
01621         void setTimer(timeout_t timeout = 0);
01622 
01632         void incTimer(timeout_t timeout);
01633 
01639         void endTimer(void);
01640 
01651         timeout_t getTimer(void) const;
01652 
01661         timeout_t getElapsed(void) const;
01662 };
01663 
01665 inline int get(Buffer &b, void *o)
01666         {return b.wait(o);};
01667 
01669 inline int put(Buffer &b, void *o)
01670         {return b.post(o);};
01671 
01673 inline int peek(Buffer &b, void *o)
01674         {return b.peek(o);};
01675 
01676 
01677 // FIXME: not in win32 implementation
01678 #if !defined(WIN32)
01679 
01680 // FIXME: private declaration ???
01681 struct  timespec *getTimeout(struct timespec *spec, timeout_t timeout); 
01682 
01683 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01684 void    wait(signo_t signo);
01685 #endif
01686 
01687 #endif // !WIN32
01688 
01689 // FIXME: no way to implement in win32
01690 #ifndef WIN32
01691 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01692 #if defined(HAVE_SYS_STREAM_H)
01693 #if defined(__linux__)
01694 #define CCXX_USE_POLL 1
01695 #endif
01696 #else
01697 #define CCXX_USE_POLL 1
01698 #endif
01699 #endif
01700 
01701 #ifdef CCXX_USE_POLL
01702 
01710 class Poller 
01711 {
01712 private:
01713         int nufds;
01714         pollfd *ufds;
01715 
01716 public:
01717         Poller();
01718 
01719         virtual ~Poller();
01720 
01728         pollfd *getList(int cnt);
01729 
01735         inline  pollfd *getList(void)
01736                 {return ufds;};
01737 };
01738 #endif
01739 #endif // !WIN32
01740 
01741 #ifdef  COMMON_STD_EXCEPTION
01742 
01748 class ThrException : public Exception
01749 {
01750 public:
01751         ThrException(const std::string &what_arg) : Exception(what_arg) {};
01752 };
01753 
01760 class SyncException : public ThrException
01761 {
01762 public:
01763         SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01764 };
01765 
01766 class InterruptException : public ThrException
01767 {
01768 public:
01769         InterruptException() : ThrException("interrupted") {};
01770 };
01771 
01772 #endif
01773 
01774 #ifdef  CCXX_NAMESPACES
01775 };
01776 #endif
01777 
01778 #endif
01779 

Generated on Thu Nov 21 12:28:31 2002 for GNU CommonC++ by doxygen1.2.18