Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

thread.h

Go to the documentation of this file.
00001 // Copyright (C) 1999-2000 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 //
00041 
00042 #ifndef __CCXX_THREAD_H__
00043 #define __CCXX_THREAD_H__
00044 #define __CCXX_POSIX
00045 
00046 #ifndef _REENTRANT
00047 #define _REENTRANT
00048 #endif
00049 
00050 #ifndef _THREAD_SAFE
00051 #define _THREAD_SAFE
00052 #endif
00053 
00054 #ifndef __CCXX_CONFIG_H__
00055 #ifdef  PACKAGE
00056 #undef  PACKAGE
00057 #endif
00058 #ifdef  VERSION
00059 #undef  VERSION
00060 #endif
00061 #include <cc++/config.h>
00062 #endif
00063 
00064 #ifndef HAVE_PTHREAD_H
00065 #include <pthread.h>
00066 #include <semaphore.h>
00067 #endif
00068 
00069 #ifndef __CCXX_MACROS_H__
00070 #include <cc++/macros.h>
00071 #else
00072 #ifdef  __CCXX_NAMESPACE_H__
00073 #include <cc++/macros.h>
00074 #endif
00075 #endif
00076 
00077 #include <time.h>
00078 #include <signal.h>
00079 #include <setjmp.h>
00080 #include <unistd.h>
00081 
00082 #ifdef  __linux__
00083 #define _SIG_THREAD_STOPCONT
00084 #define _SIG_THREAD_ALARM
00085 #endif
00086 
00087 #ifdef  _THR_UNIXWARE
00088 #define _EFTSAFE
00089 #undef  PTHREAD_MUTEXTYPE_RECURSIVE
00090 #undef  _POSIX_THREAD_PRIORITY_SCHEDULING
00091 #define sigwait(x, y) _thr_sigwait(x, y)
00092 #endif
00093 
00094 typedef pthread_t       cctid_t;
00095 typedef unsigned long   timeout_t;
00096 typedef int             signo_t;
00097 
00098 typedef enum {
00099         THROW_NOTHING, 
00100         THROW_OBJECT, 
00101         THROW_EXCEPTION
00102 }               throw_t;
00103 
00104 #define TIMEOUT_INF ~((timeout_t) 0)
00105 
00106 // use a define so that if the sys/types.h header already defines caddr_t
00107 // as it may on BSD systems, we do not break it by redefining again.
00108 
00109 #undef caddr_t
00110 #define caddr_t         char *
00111 
00112 #define ENTER_CRITICAL  EnterMutex();
00113 #define LEAVE_CRITICAL  LeaveMutex();
00114 #define ENTER_DEFERRED  setCancel(THREAD_CANCEL_DEFERRED);
00115 #define LEAVE_DEFERRED  setCancel(THREAD_CANCEL_IMMEDIATE);
00116 
00117 // These macros override common functions with thread-safe versions. In
00118 // particular the common "libc" sleep() has problems since it normally
00119 // uses SIGARLM (as actually defined by "posix").  The pthread_delay and
00120 // usleep found in libpthread are gaurenteed not to use SIGALRM and offer
00121 // higher resolution.  psleep() is defined to call the old process sleep.
00122 
00123 #undef  sleep
00124 #define sleep(x)        ccxx_sleep((x) * 1000)
00125 #define yield()         ccxx_yield()
00126 #define psleep(x)       (sleep)(x)
00127 
00128 typedef enum
00129 {
00130         THREAD_CANCEL_INITIAL=0,
00131         THREAD_CANCEL_DEFERRED=1,
00132         THREAD_CANCEL_IMMEDIATE,
00133         THREAD_CANCEL_DISABLED,
00134         THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED,
00135         THREAD_CANCEL_INVALID
00136 } thread_cancel_t;
00137 
00138 typedef enum
00139 {
00140         THREAD_SUSPEND_ENABLE,
00141         THREAD_SUSPEND_DISABLE
00142 } thread_suspend_t;
00143 
00144 #define  THREAD_SIGNAL_BLOCKED  false
00145 #define  THREAD_SIGNAL_UNBLOCK  true
00146         
00147 #ifdef  _SIG_THREAD_STOPCONT
00148 #define _SIG_THREAD_SUSPEND SIGSTOP
00149 #define _SIG_THREAD_RESUME  SIGCONT
00150 #else
00151 #ifndef SIGUSR3
00152 #ifdef  SIGWINCH
00153 #define SIGUSR3 SIGWINCH
00154 #else
00155 #define SIGUSR3 SIGINT
00156 #endif
00157 #endif
00158 #define _SIG_THREAD_SUSPEND SIGUSR3
00159 #define _SIG_THREAD_RESUME SIGUSR3
00160 #endif
00161 
00162 class Thread;
00163 
00164 Thread *getThread(void);
00165 
00166 extern "C" {
00167         void execHandler(Thread *th);
00168         void sigHandler(int signo);
00169 };
00170 
00179 class ThreadLock
00180 {
00181 private:
00182 #ifdef HAVE_PTHREAD_RWLOCK
00183         pthread_rwlock_t _lock;
00184 #else
00185         pthread_mutex_t _lock;
00186 #endif
00187 
00188 public:
00192         ThreadLock();
00193 
00197         ~ThreadLock();
00198 
00202         void ReadLock(void);
00203 
00207         void WriteLock(void);
00208 
00214         bool TryReadLock(void);
00215 
00221         bool TryWriteLock(void);
00222 
00226         void Unlock(void);
00227 };
00228 
00272 class Mutex 
00273 {
00274 private:
00275 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00276         volatile int _level;
00277         volatile Thread *_tid;
00278 #endif
00279 
00280 protected:
00289         pthread_mutex_t _mutex;
00290 
00291 public:
00295         Mutex();
00296 
00302         ~Mutex()
00303                 {pthread_mutex_destroy(&_mutex);};
00304 
00312 #ifdef  PTHREAD_MUTEXTYPE_RECURSIVE
00313         inline void EnterMutex(void)
00314                 {pthread_mutex_lock(&_mutex);};
00315 #else
00316         void    EnterMutex(void);
00317 #endif
00318 
00329         bool TryEnterMutex(void);
00330 
00341 #ifdef  PTHREAD_MUTEXTYPE_RECURSIVE
00342         inline void LeaveMutex(void)
00343                 {pthread_mutex_unlock(&_mutex);};
00344 #else
00345         void LeaveMutex(void);
00346 #endif
00347 };
00348 
00358 class MutexCounter : public Mutex
00359 {
00360 private:
00361         int     counter;
00362 
00363 public:
00364         MutexCounter(int initial = 0);
00365         
00366         friend int operator ++(MutexCounter &mc);
00367         friend int operator --(MutexCounter &mc);
00368 };
00369 
00380 class AtomicCounter
00381 {
00382 private:
00383 #ifdef  HAVE_ATOMIC
00384         atomic_t atomic;
00385 #else
00386         int counter;
00387         Mutex lock;
00388 #endif
00389 
00390 public:
00394         AtomicCounter();
00395 
00401         AtomicCounter(int value);
00402 
00403         int operator++(void);
00404         int operator--(void);
00405         int operator+=(int change);
00406         int operator-=(int change);
00407         int operator+(int change);
00408         int operator-(int change);
00409         int operator=(int value);
00410         bool operator!(void);
00411         operator int();
00412 };
00413 
00431 class Semaphore
00432 {
00433 protected:
00434         sem_t _semaphore;
00435 
00436 public:
00445         Semaphore(size_t resource = 0);
00446 
00453         ~Semaphore()
00454 #ifndef __linux__
00455                 {sem_destroy(&_semaphore);}
00456 #endif
00457         ;
00458 
00472         void Wait(void)
00473 #ifndef __linux__
00474                 {sem_wait(&_semaphore);}
00475 #endif
00476         ;
00477 
00489         bool TryWait(void)
00490 #ifndef __linux__
00491                 { return ( sem_trywait(&_semaphore) == 0 ) ? true : false; }
00492 #endif
00493         ;
00494         
00506         void Post(void)
00507 #ifndef __linux__
00508                 {sem_post(&_semaphore);}
00509 #endif
00510         ;
00511 };
00512 
00526 class Event : public Mutex
00527 {
00528 protected:
00529         pthread_cond_t _cond;
00530         bool _signaled;
00531         int _count;
00532 
00533 public:
00534         Event();
00535 
00536         ~Event()
00537                 {pthread_cond_destroy(&_cond);};
00538         
00545         void Reset(void)
00546                 {_signaled = false;};
00547 
00551         void Signal(void);
00560         bool Wait(timeout_t timer = 0);
00561 };
00562 
00584 class Buffer
00585 {
00586 private:
00587         Mutex lock_head, lock_tail;
00588         Semaphore size_head, size_tail;
00589         size_t _size;
00590         size_t _used;
00591 
00592 protected:
00598         virtual int OnPeek(void *buf) = 0;
00604         virtual int OnWait(void *buf) = 0;
00610         virtual int OnPost(void *buf) = 0;
00611 
00612 public:
00617         Buffer(size_t capacity);
00622         virtual ~Buffer()
00623                 {return;};
00624 
00629         inline size_t getSize(void)
00630                 {return _size;};
00631         
00638         inline size_t getUsed(void)
00639                 {return _used;};
00640 
00649         int Wait(void *buf);
00650 
00658         int Post(void *buf);
00659 
00666         int Peek(void *buf);
00667 
00672         virtual bool isValid(void)
00673                 {return true;};
00674 };
00675 
00683 class FixedBuffer : public Buffer
00684 {
00685 private:
00686         char *buf, *head, *tail;
00687         size_t objsize;
00688 
00689 protected:
00695         int OnPeek(void *buf);
00696 
00702         int OnWait(void *buf);
00703 
00709         int OnPost(void *buf);  
00710 
00711 public:
00719         FixedBuffer(size_t capacity, size_t objsize);
00720 
00727         FixedBuffer(const FixedBuffer &fb);
00728 
00732         ~FixedBuffer();
00733 
00734         FixedBuffer &operator=(const FixedBuffer &fb);
00735 
00736         bool isValid(void);
00737 };
00738 
00886 class Thread
00887 {
00888 private:
00889         friend class Slog;
00890 
00891         static Thread *_main;
00892 
00893 #ifndef _SIG_THREAD_ALARM
00894         static Thread *_timer;
00895         static Mutex _arm;
00896 #endif
00897         
00898         Thread *_parent;
00899         pthread_t _tid;
00900         pthread_attr_t _attr;
00901         thread_cancel_t _cancel;
00902         jmp_buf _env;
00903         time_t  _alarm;
00904         Semaphore *_start;
00905         int _msgpos;
00906         char _msgbuf[128];
00907         throw_t _throw;
00908 
00909         friend void execHandler(Thread *th);
00910         friend void sigHandler(int signo);
00911 
00912 protected:
00922         virtual void Run(void) = 0;
00923 
00930         virtual void First(void)
00931                 {return;};
00932         
00945         virtual void Final(void)
00946                 {return;};
00947 
00958         virtual void Initial(void)
00959                 {return;};
00960         
00970         virtual void *getExtended(void)
00971                 {return NULL;};
00972 
00980         virtual void Notify(Thread *th)
00981                 {return;};
00982 
00989         inline void SignalParent(signo_t signo)
00990                 {_parent->SignalThread(signo);};
00991 
00998         inline void SignalMain(signo_t signo)
00999                 {_main->SignalThread(signo);};
01000 
01005         virtual void OnTimer(void)
01006                 {return;};
01007 
01012         virtual void OnHangup(void)
01013                 {return;};
01014 
01019         virtual void OnException(void)
01020                 {return;};
01021 
01026         virtual void OnDisconnect(void)
01027                 {return;};
01028 
01033         virtual void OnPolling(void)
01034                 {return;};
01035 
01042         virtual void OnSignal(int signo)
01043                 {return;};
01044 
01054         inline void Sleep(timeout_t msec)
01055                 {ccxx_sleep(msec);};
01056 
01062         inline void Exit(void)
01063                 {longjmp(_env, 1);};
01064                
01074         void setTimer(timeout_t timer);
01081         timeout_t getTimer(void);
01087         void endTimer(void);
01094         void WaitSignal(signo_t signo);
01099         void Yield(void);
01108         void setCancel(thread_cancel_t mode);
01116         void setSuspend(thread_suspend_t mode);
01123         void setSignal(int signo, bool mode);
01132         void Terminate(void);
01133 
01137         inline void clrParent(void)
01138                 {_parent = NULL;};
01139 public:
01148         Thread(bool flag);
01161         Thread(Semaphore *start = NULL, int pri = 0, size_t stack = 0);
01169         Thread(const Thread &th);
01176         virtual ~Thread()
01177                 {Terminate();};
01178         
01191         int Start(Semaphore *start = NULL);
01192 
01199         inline Thread *getParent(void)
01200                 {return _parent;};
01201                 
01207         inline void SignalThread(int signo)
01208                 {pthread_kill(_tid, signo);};
01209 
01216 #ifdef _THR_SUNOS5
01217         inline void Suspend(void)
01218                 {thr_suspend((thread_t)_tid);};
01219 #else
01220         inline void Suspend(void)
01221                 {pthread_kill(_tid, _SIG_THREAD_SUSPEND);};
01222 #endif
01223 
01227 #ifdef  _THR_SUNOS5
01228         inline void Resume(void)
01229                 {thr_continue((thread_t)_tid);};
01230 #else
01231         inline void Resume(void)
01232                 {pthread_kill(_tid, _SIG_THREAD_RESUME);};
01233 #endif
01234 
01241         inline int getCancel(void)
01242                 {return _cancel;};
01243 
01250         bool isRunning(void);
01251 
01258         bool isThread(void);
01259 
01265         friend throw_t getException(void);
01266 
01272         friend void setException(throw_t mode);
01273 
01279         friend void ccxx_sleep(timeout_t msec);
01280 
01286         friend void suspend(Thread &th)
01287                 {pthread_kill(th._tid, _SIG_THREAD_SUSPEND);};
01288 
01294         friend void resume(Thread &th)
01295                 {pthread_kill(th._tid, _SIG_THREAD_RESUME);};
01296 
01303         friend inline void operator++(Thread &th)
01304                 {th._start->Post();};
01305 
01309         friend inline int start(Thread &th, Semaphore *start)
01310                 {return th.Start(start);};
01311 
01319         friend void siginstall(int signo);
01320 };
01321 
01336 class ThreadKey
01337 {
01338 private:
01339         pthread_key_t key;
01340 
01341 public:
01345         ThreadKey();
01349         ~ThreadKey();
01357         void *getKey(void);
01365         void setKey(void *);
01366 };
01367 
01378 class TimerPort
01379 {
01380         struct timeval timer;
01381         bool active;
01382 
01383 protected:
01390         TimerPort();
01391 
01392 public:
01401         void setTimer(timeout_t timeout = 0);
01402 
01412         void incTimer(timeout_t timeout);
01413 
01419         void endTimer(void);
01420 
01431         timeout_t getTimer(void);
01432 };
01433 
01434 inline void *getKey(ThreadKey &tk)
01435         {return tk.getKey();};
01436 
01437 inline void setKey(ThreadKey &tk, void *ptr)
01438         {tk.setKey(ptr);};
01439 
01440 inline void operator ++(Mutex &m)
01441         {m.EnterMutex();};
01442                 
01443 inline void operator --(Mutex &m)
01444         {m.LeaveMutex();};
01445 
01446 inline void operator ++(Semaphore &s)
01447         {s.Post();};
01448 
01449 inline void operator --(Semaphore &s)
01450         {s.Wait();};
01451 
01452 inline void operator ++(Event &s)
01453         {s.Signal();};
01454 
01455 inline void operator --(Event &s)
01456         {s.Wait();};
01457 
01458 /*
01459  * on some systems, signal(signum, handler) is a macro
01460  */
01461 #undef signal
01462 inline void signal(Thread &th, int signo)
01463         {th.SignalThread(signo);};
01464 
01465 inline void signal(Event &ev)
01466         {ev.Signal();};
01467 
01468 inline void signal(Semaphore &sem)
01469         {sem.Post();};
01470 
01471 inline void wait(Semaphore &sem)
01472         {sem.Wait();};
01473 
01474 inline void wait(Event &ev, timeout_t timer)
01475         {ev.Wait(timer);};
01476 
01477 inline void reset(Event &ev)
01478         {ev.Reset();};
01479 
01480 inline int get(Buffer &b, void *o)
01481         {return b.Wait(o);};
01482 
01483 inline int put(Buffer &b, void *o)
01484         {return b.Post(o);};
01485 
01486 inline int peek(Buffer &b, void *o)
01487         {return b.Peek(o);};
01488 
01489 int operator++(MutexCounter &mc);
01490 int operator--(MutexCounter &mc);
01491 
01492 struct  timespec *gettimeout(struct timespec *spec, timeout_t timeout); 
01493 void    ccxx_sleep(timeout_t msec);
01494 void    ccxx_yield(void);
01495 void    wait(signo_t signo);
01504 void    pdetach(void);
01505 
01506 #ifdef  __CCXX_NAMESPACE_H__
01507 #undef  __CCXX_NAMESPACE_H__
01508 #include <cc++/namespace.h>
01509 #endif
01510 
01511 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01512 #if defined(HAVE_SYS_STREAM_H)
01513 #if defined(__linux__)
01514 #define __CCXX_USE_POLL 1
01515 #endif
01516 #else
01517 #define __CCXX_USE_POLL 1
01518 #endif
01519 #endif
01520 
01521 #ifdef __CCXX_USE_POLL
01522 
01530 class Poller 
01531 {
01532 private:
01533         int nufds;
01534         pollfd *ufds;
01535 
01536 public:
01537         Poller();
01538 
01539         ~Poller();
01540 
01548         pollfd *getList(int cnt);
01549 
01555         inline  pollfd *getList(void)
01556                 {return ufds;};
01557 };
01558 #endif
01559 
01560 
01561 #endif
01562 

Generated at Fri Dec 15 07:08:32 2000 for CommonC++ by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000