00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
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
00107
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
00118
00119
00120
00121
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 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