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 #if defined(__FreeBSD__) && __FreeBSD__ <= 3
00065 #define _SYSV_SEMAPHORES
00066 #endif
00067
00068 #ifndef HAVE_PTHREAD_H
00069 #include <pthread.h>
00070 #ifndef _SYSV_SEMAPHORES
00071 #include <semaphore.h>
00072 #endif
00073 #endif
00074
00075 #ifndef __CCXX_MACROS_H__
00076 #include <cc++/macros.h>
00077 #else
00078 #ifdef __CCXX_NAMESPACE_H__
00079 #include <cc++/macros.h>
00080 #endif
00081 #endif
00082
00083 #include <time.h>
00084 #include <signal.h>
00085 #include <setjmp.h>
00086 #include <unistd.h>
00087
00088 #ifdef __linux__
00089 #define _SIG_THREAD_STOPCONT
00090 #define _SIG_THREAD_ALARM
00091 #endif
00092
00093 #ifdef _THR_UNIXWARE
00094 #define _EFTSAFE
00095 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00096 #undef _POSIX_THREAD_PRIORITY_SCHEDULING
00097 #define sigwait(x, y) _thr_sigwait(x, y)
00098 #endif
00099
00100 typedef pthread_t cctid_t;
00101 typedef unsigned long timeout_t;
00102 typedef int signo_t;
00103
00104 typedef enum {
00105 THROW_NOTHING,
00106 THROW_OBJECT,
00107 THROW_EXCEPTION
00108 } throw_t;
00109
00110 #define TIMEOUT_INF ~((timeout_t) 0)
00111
00112
00113
00114
00115 #undef caddr_t
00116 #define caddr_t char *
00117
00118 #define ENTER_CRITICAL EnterMutex();
00119 #define LEAVE_CRITICAL LeaveMutex();
00120 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00121 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00122
00123
00124
00125
00126
00127
00128
00129 #undef sleep
00130 #define sleep(x) ccxx_sleep((x) * 1000)
00131 #define yield() ccxx_yield()
00132 #define psleep(x) (sleep)(x)
00133
00134 typedef enum
00135 {
00136 THREAD_CANCEL_INITIAL=0,
00137 THREAD_CANCEL_DEFERRED=1,
00138 THREAD_CANCEL_IMMEDIATE,
00139 THREAD_CANCEL_DISABLED,
00140 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED,
00141 THREAD_CANCEL_INVALID
00142 } thread_cancel_t;
00143
00144 typedef enum
00145 {
00146 THREAD_SUSPEND_ENABLE,
00147 THREAD_SUSPEND_DISABLE
00148 } thread_suspend_t;
00149
00150 #define THREAD_SIGNAL_BLOCKED false
00151 #define THREAD_SIGNAL_UNBLOCK true
00152
00153 #ifdef _SIG_THREAD_STOPCONT
00154 #define _SIG_THREAD_SUSPEND SIGSTOP
00155 #define _SIG_THREAD_RESUME SIGCONT
00156 #else
00157 #ifndef SIGUSR3
00158 #ifdef SIGWINCH
00159 #define SIGUSR3 SIGWINCH
00160 #else
00161 #define SIGUSR3 SIGINT
00162 #endif
00163 #endif
00164 #define _SIG_THREAD_SUSPEND SIGUSR3
00165 #define _SIG_THREAD_RESUME SIGUSR3
00166 #endif
00167
00168 class Thread;
00169
00170 Thread *getThread(void);
00171
00172 extern "C" {
00173 void execHandler(Thread *th);
00174 void sigHandler(int signo);
00175 };
00176
00185 class ThreadLock
00186 {
00187 private:
00188 #ifdef HAVE_PTHREAD_RWLOCK
00189 pthread_rwlock_t _lock;
00190 #else
00191 pthread_mutex_t _lock;
00192 #endif
00193
00194 public:
00198 ThreadLock();
00199
00203 ~ThreadLock();
00204
00208 void ReadLock(void);
00209
00213 void WriteLock(void);
00214
00220 bool TryReadLock(void);
00221
00227 bool TryWriteLock(void);
00228
00232 void Unlock(void);
00233 };
00234
00278 class Mutex
00279 {
00280 private:
00281 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00282 volatile int _level;
00283 volatile Thread *_tid;
00284 #endif
00285
00286 protected:
00295 pthread_mutex_t _mutex;
00296
00297 public:
00301 Mutex();
00302
00308 ~Mutex()
00309 {pthread_mutex_destroy(&_mutex);};
00310
00318 #ifdef PTHREAD_MUTEXTYPE_RECURSIVE
00319 inline void EnterMutex(void)
00320 {pthread_mutex_lock(&_mutex);};
00321 #else
00322 void EnterMutex(void);
00323 #endif
00324
00335 bool TryEnterMutex(void);
00336
00347 #ifdef PTHREAD_MUTEXTYPE_RECURSIVE
00348 inline void LeaveMutex(void)
00349 {pthread_mutex_unlock(&_mutex);};
00350 #else
00351 void LeaveMutex(void);
00352 #endif
00353 };
00354
00364 class MutexCounter : public Mutex
00365 {
00366 private:
00367 int counter;
00368
00369 public:
00370 MutexCounter(int initial = 0);
00371
00372 friend int operator ++(MutexCounter &mc);
00373 friend int operator --(MutexCounter &mc);
00374 };
00375
00386 class AtomicCounter
00387 {
00388 private:
00389 #ifdef HAVE_ATOMIC
00390 atomic_t atomic;
00391 #else
00392 int counter;
00393 Mutex lock;
00394 #endif
00395
00396 public:
00400 AtomicCounter();
00401
00407 AtomicCounter(int value);
00408
00409 int operator++(void);
00410 int operator--(void);
00411 int operator+=(int change);
00412 int operator-=(int change);
00413 int operator+(int change);
00414 int operator-(int change);
00415 int operator=(int value);
00416 bool operator!(void);
00417 operator int();
00418 };
00419
00430 class Conditional : public Mutex
00431 {
00432 protected:
00433 pthread_cond_t _cond;
00434
00435 public:
00439 Conditional();
00440
00444 ~Conditional()
00445 {pthread_cond_destroy(&_cond);};
00446
00452 void Signal(bool broadcast);
00453
00457 void Wait(timeout_t timer = 0);
00458 };
00459
00477 class Semaphore
00478 {
00479 protected:
00480 #ifdef _SYSV_SEMAPHORES
00481 int _semaphore;
00482 #else
00483 sem_t _semaphore;
00484 #endif
00485
00486 public:
00495 Semaphore(size_t resource = 0);
00496
00503 ~Semaphore()
00504 #if !defined(__linux__) && !defined(_SYSV_SEMAPHORES)
00505 {sem_destroy(&_semaphore);}
00506 #endif
00507 ;
00508
00522 void Wait(void)
00523 #if !defined(__linux__) && !defined(_SYSV_SEMAPHORES)
00524 {sem_wait(&_semaphore);}
00525 #endif
00526 ;
00527
00539 bool TryWait(void)
00540 #if !defined(__linux__) && !defined(_SYSV_SEMAPHORES)
00541 { return ( sem_trywait(&_semaphore) == 0 ) ? true : false; }
00542 #endif
00543 ;
00544
00556 void Post(void)
00557 #if !defined(__linux__) && !defined(_SYSV_SEMAPHORES)
00558 {sem_post(&_semaphore);}
00559 #endif
00560 ;
00561
00567 int getValue(void);
00568 };
00569
00583 class Event : public Mutex
00584 {
00585 protected:
00586 pthread_cond_t _cond;
00587 bool _signaled;
00588 int _count;
00589
00590 public:
00591 Event();
00592
00593 ~Event()
00594 {pthread_cond_destroy(&_cond);};
00595
00602 void Reset(void)
00603 {_signaled = false;};
00604
00608 void Signal(void);
00617 bool Wait(timeout_t timer = 0);
00618 };
00619
00641 class Buffer
00642 {
00643 private:
00644 Mutex lock_head, lock_tail;
00645 Semaphore size_head, size_tail;
00646 size_t _size;
00647 size_t _used;
00648
00649 protected:
00655 virtual int OnPeek(void *buf) = 0;
00661 virtual int OnWait(void *buf) = 0;
00667 virtual int OnPost(void *buf) = 0;
00668
00669 public:
00674 Buffer(size_t capacity);
00679 virtual ~Buffer()
00680 {return;};
00681
00686 inline size_t getSize(void)
00687 {return _size;};
00688
00695 inline size_t getUsed(void)
00696 {return _used;};
00697
00706 int Wait(void *buf);
00707
00715 int Post(void *buf);
00716
00723 int Peek(void *buf);
00724
00729 virtual bool isValid(void)
00730 {return true;};
00731 };
00732
00740 class FixedBuffer : public Buffer
00741 {
00742 private:
00743 char *buf, *head, *tail;
00744 size_t objsize;
00745
00746 protected:
00752 int OnPeek(void *buf);
00753
00759 int OnWait(void *buf);
00760
00766 int OnPost(void *buf);
00767
00768 public:
00776 FixedBuffer(size_t capacity, size_t objsize);
00777
00784 FixedBuffer(const FixedBuffer &fb);
00785
00789 ~FixedBuffer();
00790
00791 FixedBuffer &operator=(const FixedBuffer &fb);
00792
00793 bool isValid(void);
00794 };
00795
00943 class Thread
00944 {
00945 private:
00946 friend class Slog;
00947
00948 static Thread *_main;
00949
00950 #ifndef _SIG_THREAD_ALARM
00951 static Thread *_timer;
00952 static Mutex _arm;
00953 #endif
00954
00955 Thread *_parent;
00956 pthread_t _tid;
00957 pthread_attr_t _attr;
00958 thread_cancel_t _cancel;
00959 jmp_buf _env;
00960 time_t _alarm;
00961 Semaphore *_start;
00962 int _msgpos;
00963 char _msgbuf[128];
00964 throw_t _throw;
00965
00966 friend void execHandler(Thread *th);
00967 friend void sigHandler(int signo);
00968 friend Thread *getThread(void);
00969
00970 protected:
00980 virtual void Run(void) = 0;
00981
00988 virtual void First(void)
00989 {return;};
00990
01003 virtual void Final(void)
01004 {return;};
01005
01016 virtual void Initial(void)
01017 {return;};
01018
01028 virtual void *getExtended(void)
01029 {return NULL;};
01030
01038 virtual void Notify(Thread *th)
01039 {return;};
01040
01047 inline void SignalParent(signo_t signo)
01048 {_parent->SignalThread(signo);};
01049
01056 inline void SignalMain(signo_t signo)
01057 {_main->SignalThread(signo);};
01058
01063 virtual void OnTimer(void)
01064 {return;};
01065
01070 virtual void OnHangup(void)
01071 {return;};
01072
01077 virtual void OnException(void)
01078 {return;};
01079
01084 virtual void OnDisconnect(void)
01085 {return;};
01086
01091 virtual void OnPolling(void)
01092 {return;};
01093
01100 virtual void OnSignal(int signo)
01101 {return;};
01102
01112 inline void Sleep(timeout_t msec)
01113 {ccxx_sleep(msec);};
01114
01120 inline void Exit(void)
01121 {longjmp(_env, 1);};
01122
01132 void setTimer(timeout_t timer);
01139 timeout_t getTimer(void);
01145 void endTimer(void);
01152 void WaitSignal(signo_t signo);
01157 void Yield(void);
01161 void testCancel(void);
01170 void setCancel(thread_cancel_t mode);
01178 void setSuspend(thread_suspend_t mode);
01185 void setSignal(int signo, bool mode);
01194 void Terminate(void);
01195
01199 inline void clrParent(void)
01200 {_parent = NULL;};
01201 public:
01210 Thread(bool flag);
01223 Thread(Semaphore *start = NULL, int pri = 0, size_t stack = 0);
01231 Thread(const Thread &th);
01238 virtual ~Thread()
01239 {Terminate();};
01240
01253 int Start(Semaphore *start = NULL);
01254
01263 int Detach(Semaphore *start = NULL);
01264
01271 inline Thread *getParent(void)
01272 {return _parent;};
01273
01279 inline void SignalThread(int signo)
01280 {pthread_kill(_tid, signo);};
01281
01288 #ifdef _THR_SUNOS5
01289 inline void Suspend(void)
01290 {thr_suspend((thread_t)_tid);};
01291 #else
01292 inline void Suspend(void)
01293 {pthread_kill(_tid, _SIG_THREAD_SUSPEND);};
01294 #endif
01295
01299 #ifdef _THR_SUNOS5
01300 inline void Resume(void)
01301 {thr_continue((thread_t)_tid);};
01302 #else
01303 inline void Resume(void)
01304 {pthread_kill(_tid, _SIG_THREAD_RESUME);};
01305 #endif
01306
01313 inline int getCancel(void)
01314 {return _cancel;};
01315
01322 bool isRunning(void);
01323
01330 bool isThread(void);
01331
01337 friend throw_t getException(void);
01338
01344 friend void setException(throw_t mode);
01345
01351 friend void ccxx_sleep(timeout_t msec);
01352
01358 friend void suspend(Thread &th)
01359 {pthread_kill(th._tid, _SIG_THREAD_SUSPEND);};
01360
01366 friend void resume(Thread &th)
01367 {pthread_kill(th._tid, _SIG_THREAD_RESUME);};
01368
01375 friend inline void operator++(Thread &th)
01376 {th._start->Post();};
01377
01378 friend inline void operator--(Thread &th)
01379 {th._start->Wait();};
01380
01384 friend inline int start(Thread &th, Semaphore *start)
01385 {return th.Start(start);};
01386
01394 friend void siginstall(int signo);
01395 };
01396
01411 class ThreadKey
01412 {
01413 private:
01414 pthread_key_t key;
01415
01416 public:
01420 ThreadKey();
01424 ~ThreadKey();
01432 void *getKey(void);
01440 void setKey(void *);
01441 };
01442
01453 class TimerPort
01454 {
01455 struct timeval timer;
01456 bool active;
01457
01458 public:
01465 TimerPort();
01466
01475 void setTimer(timeout_t timeout = 0);
01476
01486 void incTimer(timeout_t timeout);
01487
01493 void endTimer(void);
01494
01505 timeout_t getTimer(void);
01506
01515 timeout_t getElapsed(void);
01516 };
01517
01518 inline void *getKey(ThreadKey &tk)
01519 {return tk.getKey();};
01520
01521 inline void setKey(ThreadKey &tk, void *ptr)
01522 {tk.setKey(ptr);};
01523
01524 inline void operator ++(Mutex &m)
01525 {m.EnterMutex();};
01526
01527 inline void operator --(Mutex &m)
01528 {m.LeaveMutex();};
01529
01530 inline void operator ++(Semaphore &s)
01531 {s.Post();};
01532
01533 inline void operator --(Semaphore &s)
01534 {s.Wait();};
01535
01536 inline void operator ++(Event &s)
01537 {s.Signal();};
01538
01539 inline void operator --(Event &s)
01540 {s.Wait();};
01541
01542
01543
01544
01545 #undef signal
01546 inline void signal(Thread &th, int signo)
01547 {th.SignalThread(signo);};
01548
01549 inline void signal(Event &ev)
01550 {ev.Signal();};
01551
01552 inline void signal(Semaphore &sem)
01553 {sem.Post();};
01554
01555 inline void wait(Semaphore &sem)
01556 {sem.Wait();};
01557
01558 inline void wait(Event &ev, timeout_t timer)
01559 {ev.Wait(timer);};
01560
01561 inline void reset(Event &ev)
01562 {ev.Reset();};
01563
01564 inline int get(Buffer &b, void *o)
01565 {return b.Wait(o);};
01566
01567 inline int put(Buffer &b, void *o)
01568 {return b.Post(o);};
01569
01570 inline int peek(Buffer &b, void *o)
01571 {return b.Peek(o);};
01572
01573 int operator++(MutexCounter &mc);
01574 int operator--(MutexCounter &mc);
01575
01576 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01577 void ccxx_sleep(timeout_t msec);
01578 void ccxx_yield(void);
01579 void wait(signo_t signo);
01588 void pdetach(void);
01589
01590 #ifdef __CCXX_NAMESPACE_H__
01591 #undef __CCXX_NAMESPACE_H__
01592 #include <cc++/namespace.h>
01593 #endif
01594
01595 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01596 #if defined(HAVE_SYS_STREAM_H)
01597 #if defined(__linux__)
01598 #define __CCXX_USE_POLL 1
01599 #endif
01600 #else
01601 #define __CCXX_USE_POLL 1
01602 #endif
01603 #endif
01604
01605 #ifdef __CCXX_USE_POLL
01606
01614 class Poller
01615 {
01616 private:
01617 int nufds;
01618 pollfd *ufds;
01619
01620 public:
01621 Poller();
01622
01623 ~Poller();
01624
01632 pollfd *getList(int cnt);
01633
01639 inline pollfd *getList(void)
01640 {return ufds;};
01641 };
01642 #endif
01643
01644
01645 #endif
01646