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
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 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