Google

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 
00517         int getValue(void);
00518 };
00519 
00533 class Event : public Mutex
00534 {
00535 protected:
00536         pthread_cond_t _cond;
00537         bool _signaled;
00538         int _count;
00539 
00540 public:
00541         Event();
00542 
00543         ~Event()
00544                 {pthread_cond_destroy(&_cond);};
00545         
00552         void Reset(void)
00553                 {_signaled = false;};
00554 
00558         void Signal(void);
00567         bool Wait(timeout_t timer = 0);
00568 };
00569 
00591 class Buffer
00592 {
00593 private:
00594         Mutex lock_head, lock_tail;
00595         Semaphore size_head, size_tail;
00596         size_t _size;
00597         size_t _used;
00598 
00599 protected:
00605         virtual int OnPeek(void *buf) = 0;
00611         virtual int OnWait(void *buf) = 0;
00617         virtual int OnPost(void *buf) = 0;
00618 
00619 public:
00624         Buffer(size_t capacity);
00629         virtual ~Buffer()
00630                 {return;};
00631 
00636         inline size_t getSize(void)
00637                 {return _size;};
00638         
00645         inline size_t getUsed(void)
00646                 {return _used;};
00647 
00656         int Wait(void *buf);
00657 
00665         int Post(void *buf);
00666 
00673         int Peek(void *buf);
00674 
00679         virtual bool isValid(void)
00680                 {return true;};
00681 };
00682 
00690 class FixedBuffer : public Buffer
00691 {
00692 private:
00693         char *buf, *head, *tail;
00694         size_t objsize;
00695 
00696 protected:
00702         int OnPeek(void *buf);
00703 
00709         int OnWait(void *buf);
00710 
00716         int OnPost(void *buf);  
00717 
00718 public:
00726         FixedBuffer(size_t capacity, size_t objsize);
00727 
00734         FixedBuffer(const FixedBuffer &fb);
00735 
00739         ~FixedBuffer();
00740 
00741         FixedBuffer &operator=(const FixedBuffer &fb);
00742 
00743         bool isValid(void);
00744 };
00745 
00893 class Thread
00894 {
00895 private:
00896         friend class Slog;
00897 
00898         static Thread *_main;
00899 
00900 #ifndef _SIG_THREAD_ALARM
00901         static Thread *_timer;
00902         static Mutex _arm;
00903 #endif
00904         
00905         Thread *_parent;
00906         pthread_t _tid;
00907         pthread_attr_t _attr;
00908         thread_cancel_t _cancel;
00909         jmp_buf _env;
00910         time_t  _alarm;
00911         Semaphore *_start;
00912         int _msgpos;
00913         char _msgbuf[128];
00914         throw_t _throw;
00915 
00916         friend void execHandler(Thread *th);
00917         friend void sigHandler(int signo);
00918         friend Thread *getThread(void);
00919 
00920 protected:
00930         virtual void Run(void) = 0;
00931 
00938         virtual void First(void)
00939                 {return;};
00940         
00953         virtual void Final(void)
00954                 {return;};
00955 
00966         virtual void Initial(void)
00967                 {return;};
00968         
00978         virtual void *getExtended(void)
00979                 {return NULL;};
00980 
00988         virtual void Notify(Thread *th)
00989                 {return;};
00990 
00997         inline void SignalParent(signo_t signo)
00998                 {_parent->SignalThread(signo);};
00999 
01006         inline void SignalMain(signo_t signo)
01007                 {_main->SignalThread(signo);};
01008 
01013         virtual void OnTimer(void)
01014                 {return;};
01015 
01020         virtual void OnHangup(void)
01021                 {return;};
01022 
01027         virtual void OnException(void)
01028                 {return;};
01029 
01034         virtual void OnDisconnect(void)
01035                 {return;};
01036 
01041         virtual void OnPolling(void)
01042                 {return;};
01043 
01050         virtual void OnSignal(int signo)
01051                 {return;};
01052 
01062         inline void Sleep(timeout_t msec)
01063                 {ccxx_sleep(msec);};
01064 
01070         inline void Exit(void)
01071                 {longjmp(_env, 1);};
01072                
01082         void setTimer(timeout_t timer);
01089         timeout_t getTimer(void);
01095         void endTimer(void);
01102         void WaitSignal(signo_t signo);
01107         void Yield(void);
01111         void testCancel(void);
01120         void setCancel(thread_cancel_t mode);
01128         void setSuspend(thread_suspend_t mode);
01135         void setSignal(int signo, bool mode);
01144         void Terminate(void);
01145 
01149         inline void clrParent(void)
01150                 {_parent = NULL;};
01151 public:
01160         Thread(bool flag);
01173         Thread(Semaphore *start = NULL, int pri = 0, size_t stack = 0);
01181         Thread(const Thread &th);
01188         virtual ~Thread()
01189                 {Terminate();};
01190         
01203         int Start(Semaphore *start = NULL);
01204 
01211         inline Thread *getParent(void)
01212                 {return _parent;};
01213                 
01219         inline void SignalThread(int signo)
01220                 {pthread_kill(_tid, signo);};
01221 
01228 #ifdef _THR_SUNOS5
01229         inline void Suspend(void)
01230                 {thr_suspend((thread_t)_tid);};
01231 #else
01232         inline void Suspend(void)
01233                 {pthread_kill(_tid, _SIG_THREAD_SUSPEND);};
01234 #endif
01235 
01239 #ifdef  _THR_SUNOS5
01240         inline void Resume(void)
01241                 {thr_continue((thread_t)_tid);};
01242 #else
01243         inline void Resume(void)
01244                 {pthread_kill(_tid, _SIG_THREAD_RESUME);};
01245 #endif
01246 
01253         inline int getCancel(void)
01254                 {return _cancel;};
01255 
01262         bool isRunning(void);
01263 
01270         bool isThread(void);
01271 
01277         friend throw_t getException(void);
01278 
01284         friend void setException(throw_t mode);
01285 
01291         friend void ccxx_sleep(timeout_t msec);
01292 
01298         friend void suspend(Thread &th)
01299                 {pthread_kill(th._tid, _SIG_THREAD_SUSPEND);};
01300 
01306         friend void resume(Thread &th)
01307                 {pthread_kill(th._tid, _SIG_THREAD_RESUME);};
01308 
01315         friend inline void operator++(Thread &th)
01316                 {th._start->Post();};
01317 
01318         friend inline void operator--(Thread &th)
01319                 {th._start->Wait();};
01320 
01324         friend inline int start(Thread &th, Semaphore *start)
01325                 {return th.Start(start);};
01326 
01334         friend void siginstall(int signo);
01335 };
01336 
01351 class ThreadKey
01352 {
01353 private:
01354         pthread_key_t key;
01355 
01356 public:
01360         ThreadKey();
01364         ~ThreadKey();
01372         void *getKey(void);
01380         void setKey(void *);
01381 };
01382 
01393 class TimerPort
01394 {
01395         struct timeval timer;
01396         bool active;
01397 
01398 protected:
01405         TimerPort();
01406 
01407 public:
01416         void setTimer(timeout_t timeout = 0);
01417 
01427         void incTimer(timeout_t timeout);
01428 
01434         void endTimer(void);
01435 
01446         timeout_t getTimer(void);
01447 };
01448 
01449 inline void *getKey(ThreadKey &tk)
01450         {return tk.getKey();};
01451 
01452 inline void setKey(ThreadKey &tk, void *ptr)
01453         {tk.setKey(ptr);};
01454 
01455 inline void operator ++(Mutex &m)
01456         {m.EnterMutex();};
01457                 
01458 inline void operator --(Mutex &m)
01459         {m.LeaveMutex();};
01460 
01461 inline void operator ++(Semaphore &s)
01462         {s.Post();};
01463 
01464 inline void operator --(Semaphore &s)
01465         {s.Wait();};
01466 
01467 inline void operator ++(Event &s)
01468         {s.Signal();};
01469 
01470 inline void operator --(Event &s)
01471         {s.Wait();};
01472 
01473 /*
01474  * on some systems, signal(signum, handler) is a macro
01475  */
01476 #undef signal
01477 inline void signal(Thread &th, int signo)
01478         {th.SignalThread(signo);};
01479 
01480 inline void signal(Event &ev)
01481         {ev.Signal();};
01482 
01483 inline void signal(Semaphore &sem)
01484         {sem.Post();};
01485 
01486 inline void wait(Semaphore &sem)
01487         {sem.Wait();};
01488 
01489 inline void wait(Event &ev, timeout_t timer)
01490         {ev.Wait(timer);};
01491 
01492 inline void reset(Event &ev)
01493         {ev.Reset();};
01494 
01495 inline int get(Buffer &b, void *o)
01496         {return b.Wait(o);};
01497 
01498 inline int put(Buffer &b, void *o)
01499         {return b.Post(o);};
01500 
01501 inline int peek(Buffer &b, void *o)
01502         {return b.Peek(o);};
01503 
01504 int operator++(MutexCounter &mc);
01505 int operator--(MutexCounter &mc);
01506 
01507 struct  timespec *gettimeout(struct timespec *spec, timeout_t timeout); 
01508 void    ccxx_sleep(timeout_t msec);
01509 void    ccxx_yield(void);
01510 void    wait(signo_t signo);
01519 void    pdetach(void);
01520 
01521 #ifdef  __CCXX_NAMESPACE_H__
01522 #undef  __CCXX_NAMESPACE_H__
01523 #include <cc++/namespace.h>
01524 #endif
01525 
01526 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01527 #if defined(HAVE_SYS_STREAM_H)
01528 #if defined(__linux__)
01529 #define __CCXX_USE_POLL 1
01530 #endif
01531 #else
01532 #define __CCXX_USE_POLL 1
01533 #endif
01534 #endif
01535 
01536 #ifdef __CCXX_USE_POLL
01537 
01545 class Poller 
01546 {
01547 private:
01548         int nufds;
01549         pollfd *ufds;
01550 
01551 public:
01552         Poller();
01553 
01554         ~Poller();
01555 
01563         pollfd *getList(int cnt);
01564 
01570         inline  pollfd *getList(void)
01571                 {return ufds;};
01572 };
01573 #endif
01574 
01575 
01576 #endif
01577 

Generated at Fri Mar 23 10:47:54 2001 for CommonC++ by doxygen1.2.1 written by Dimitri van Heesch, © 1997-2000