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
00046 #ifndef CCXX_THREAD_H_
00047 #define CCXX_THREAD_H_
00048
00049 #ifndef WIN32
00050 #define CCXX_POSIX
00051 #endif // !WIN32
00052
00053 #ifndef CCXX_CONFIG_H_
00054 #include <cc++/config.h>
00055 #endif
00056
00057 #ifndef CCXX_EXCEPTION_H_
00058 #include <cc++/exception.h>
00059 #endif
00060
00061 #ifndef WIN32
00062 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00063 #define CCXX_SYSV_SEMAPHORES
00064 #endif
00065
00066 #ifdef MACOSX
00067 #define CCXX_NAMED_SEMAPHORES
00068 #define CCXX_BROKEN_SEMGETVALUE
00069 #endif
00070
00071 #ifndef HAVE_PTHREAD_H
00072 #include <pthread.h>
00073 #ifndef CCXX_SYSV_SEMAPHORES
00074 #include <semaphore.h>
00075 #endif
00076 #endif
00077 #endif // !WIN32
00078
00079 #undef CCXX_USE_WIN32_ATOMIC
00080 #ifndef WIN32
00081 #include <time.h>
00082 #include <signal.h>
00083 #include <unistd.h>
00084
00085 #ifdef _THR_UNIXWARE
00086 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00087 #endif
00088
00089 typedef pthread_t cctid_t;
00090 typedef unsigned long timeout_t;
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #else // WIN32
00102 typedef DWORD cctid_t;
00103 typedef DWORD timeout_t;
00104
00105 #define MAX_SEM_VALUE 1000000
00106 #define CCXX_USE_WIN32_ATOMIC 1
00107 #if defined(__CYGWIN32__)
00108
00109 #else
00110 #if _MSC_VER < 1300
00111 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00112 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00113 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00114 #endif
00115 #endif
00116
00117 #endif // !WIN32
00118
00119 #ifdef CCXX_NAMESPACES
00120 namespace ost {
00121 #endif
00122
00123 class CCXX_CLASS_EXPORT Thread;
00124 class CCXX_CLASS_EXPORT ThreadKey;
00125
00126 #define TIMEOUT_INF ~((timeout_t) 0)
00127
00128 #define ENTER_CRITICAL enterMutex();
00129 #define LEAVE_CRITICAL leaveMutex();
00130 #define ENTER_DEFERRED setCancel(cancelDeferred);
00131 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00132
00133 #ifndef WIN32
00134
00135
00136
00137
00138
00139
00140 #undef sleep
00141 #define psleep(x) (sleep)(x)
00142
00143 #endif // !WIN32
00144
00145 #undef Yield
00146
00147 #ifdef WIN32
00148 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00149 #endif
00150
00151 class Conditional;
00152 class CCXX_CLASS_EXPORT Event;
00153
00197 class CCXX_CLASS_EXPORT Mutex
00198 {
00199 friend class Conditional;
00200 friend class Event;
00201 private:
00202 #ifndef WIN32
00203 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00204 volatile int _level;
00205 volatile Thread *_tid;
00206 #endif
00207
00208
00209
00210
00211
00212
00213
00214
00215 pthread_mutex_t _mutex;
00216 #else
00217 HANDLE mutex;
00218 #endif
00219
00220 public:
00224 Mutex();
00225
00231 virtual ~Mutex();
00232
00240 void enterMutex(void);
00241
00252 bool tryEnterMutex(void);
00253
00264 void leaveMutex(void);
00265 };
00266
00288 class MutexLock
00289 {
00290 private:
00291 Mutex& mutex;
00292 public:
00296 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00297 { mutex.enterMutex(); }
00301
00302 ~MutexLock()
00303 { mutex.leaveMutex(); }
00304 };
00305
00314 class CCXX_CLASS_EXPORT ThreadLock
00315 {
00316 private:
00317 #ifdef HAVE_PTHREAD_RWLOCK
00318 pthread_rwlock_t _lock;
00319 #else
00320 Mutex mutex;
00321 #endif
00322
00323 public:
00327 ThreadLock();
00328
00332 virtual ~ThreadLock();
00333
00337 void readLock(void);
00338
00342 void writeLock(void);
00343
00349 bool tryReadLock(void);
00350
00356 bool tryWriteLock(void);
00357
00361 void unlock(void);
00362 };
00363
00373 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00374 {
00375 private:
00376 int counter;
00377
00378 public:
00379 MutexCounter();
00380 MutexCounter(int initial);
00381
00382 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00383 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00384 };
00385
00396 class CCXX_CLASS_EXPORT AtomicCounter
00397 {
00398 #ifndef CCXX_USE_WIN32_ATOMIC
00399 private:
00400 #ifdef HAVE_ATOMIC
00401 atomic_t atomic;
00402 #else
00403 int counter;
00404 Mutex lock;
00405 #endif
00406
00407 public:
00411 AtomicCounter();
00412
00418 AtomicCounter(int value);
00419
00420 int operator++(void);
00421 int operator--(void);
00422 int operator+=(int change);
00423 int operator-=(int change);
00424 int operator+(int change);
00425 int operator-(int change);
00426 int operator=(int value);
00427 bool operator!(void);
00428 operator int();
00429 #else
00430 private:
00431 long atomic;
00432
00433 public:
00434 inline AtomicCounter()
00435 {atomic = 0;};
00436
00437 inline AtomicCounter(int value)
00438 {atomic = value;};
00439
00440 inline int operator++(void)
00441 {return InterlockedIncrement(&atomic);};
00442
00443 inline int operator--(void)
00444 {return InterlockedDecrement(&atomic);};
00445
00446 int operator+=(int change);
00447
00448 int operator-=(int change);
00449
00450 inline int operator+(int change)
00451 {return atomic + change;};
00452
00453 inline int operator-(int change)
00454 {return atomic - change;};
00455
00456 inline int operator=(int value)
00457 {return InterlockedExchange(&atomic, value);};
00458
00459 inline bool operator!(void)
00460 {return (atomic == 0) ? true : false;};
00461
00462 inline operator int()
00463 {return atomic;};
00464 #endif
00465 };
00466
00467 #ifndef WIN32
00468
00488 class Conditional : public Mutex
00489 {
00490 private:
00491 pthread_cond_t _cond;
00492
00493 public:
00497 Conditional();
00498
00502 virtual ~Conditional();
00503
00509 void signal(bool broadcast);
00510
00514 void wait(timeout_t timer = 0);
00515 };
00516 #endif
00517
00535 class CCXX_CLASS_EXPORT Semaphore
00536 {
00537 private:
00538 #ifndef WIN32
00539 #ifdef CCXX_SYSV_SEMAPHORES
00540 int _semaphore;
00541 #else
00542 sem_t _semaphore;
00543 sem_t *_semobject;
00544 #endif
00545 #else // WIN32
00546 HANDLE semObject;
00547 #endif // !WIN32
00548
00549 public:
00558 Semaphore(size_t resource = 0);
00559
00566 virtual ~Semaphore();
00567
00581 void wait(void);
00582
00594 bool tryWait(void);
00595
00607 void post(void);
00608
00609
00615 #ifndef WIN32
00616 #ifndef __CYGWIN32__
00617 int getValue(void);
00618 #endif
00619 #endif
00620 };
00621
00635 class CCXX_CLASS_EXPORT Event
00636 {
00637 private:
00638 #ifndef WIN32
00639 Mutex mutex;
00640 pthread_cond_t _cond;
00641 bool _signaled;
00642 int _count;
00643 #else
00644 HANDLE cond;
00645 #endif
00646
00647 public:
00648 Event();
00649
00650 virtual ~Event();
00651
00658 void reset(void);
00659
00663 void signal(void);
00664
00673 bool wait(timeout_t timer);
00674 bool wait(void);
00675 };
00676
00698 class CCXX_CLASS_EXPORT Buffer
00699 {
00700 private:
00701 Mutex lock_head, lock_tail;
00702 Semaphore size_head, size_tail;
00703 size_t _size;
00704 size_t _used;
00705
00706 protected:
00712 virtual int onPeek(void *buf) = 0;
00718 virtual int onWait(void *buf) = 0;
00724 virtual int onPost(void *buf) = 0;
00725
00726 public:
00731 Buffer(size_t capacity);
00736 virtual ~Buffer()
00737 {return;};
00738
00743 inline size_t getSize(void)
00744 {return _size;};
00745
00752 inline size_t getUsed(void)
00753 {return _used;};
00754
00763 int wait(void *buf);
00764
00772 int post(void *buf);
00773
00780 int peek(void *buf);
00781
00786 virtual bool isValid(void)
00787 {return true;};
00788 };
00789
00797 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00798 {
00799 private:
00800 char *buf, *head, *tail;
00801 size_t objsize;
00802
00803 protected:
00809 int onPeek(void *buf);
00810
00816 int onWait(void *buf);
00817
00823 int onPost(void *buf);
00824
00825 public:
00833 FixedBuffer(size_t capacity, size_t objsize);
00834
00841 FixedBuffer(const FixedBuffer &fb);
00842
00846 virtual ~FixedBuffer();
00847
00848 FixedBuffer &operator=(const FixedBuffer &fb);
00849
00850 bool isValid(void);
00851 };
00852
01034 class CCXX_CLASS_EXPORT Thread
01035 {
01036 public:
01040 typedef enum Throw {
01041 throwNothing,
01042 throwObject,
01043 throwException
01044 } Throw;
01045
01049 typedef enum Cancel
01050 {
01051 cancelInitial=0,
01052 cancelDeferred=1,
01053 cancelImmediate,
01054 cancelDisabled,
01055 cancelManual,
01057 cancelDefault=cancelDeferred
01059 } Cancel;
01060
01064 typedef enum Suspend
01065 {
01066 suspendEnable,
01067 suspendDisable
01068 } Suspend;
01069
01070 #ifndef WIN32
01071
01072 friend class PosixThread;
01073 #endif
01074
01075 friend class DummyThread;
01076 private:
01077 friend class Slog;
01078
01079 Semaphore joinSem;
01080 static Thread* _main;
01081
01082 Thread *_parent;
01083 enum Cancel _cancel;
01084 Semaphore *_start;
01085
01086
01087 friend class ThreadImpl;
01088 class ThreadImpl* priv;
01089
01090 #ifndef WIN32
01091 friend Thread *getThread(void);
01092 #else
01093 static unsigned __stdcall Execute(Thread *th);
01094 #endif
01095
01096
01097 void close();
01098
01099 protected:
01109 virtual void run(void) = 0;
01110
01132 virtual void final(void)
01133 {return;};
01134
01146 virtual void initial(void)
01147 {return;};
01148
01158 virtual void* getExtended(void)
01159 {return NULL;};
01160
01168 virtual void notify(Thread*)
01169 {return;};
01170
01176 void exit(void);
01177
01181 bool testCancel(void);
01182
01192 void setCancel(Cancel mode);
01193
01201 void setSuspend(Suspend mode);
01202
01211 void terminate(void);
01212
01216 inline void clrParent(void)
01217 {_parent = NULL;};
01218
01219 #ifdef WIN32
01220
01221 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01222 #endif
01223
01224 public:
01233 Thread(bool isMain);
01234
01246 Thread(int pri = 0, size_t stack = 0);
01247
01248 #ifndef WIN32
01249
01257 Thread(const Thread &th);
01258 #endif
01259
01266 virtual ~Thread();
01267
01277 static void sleep(timeout_t msec);
01278
01283 static void yield(void);
01284
01297 int start(Semaphore *start = 0);
01298
01307 int detach(Semaphore *start = 0);
01308
01315 inline Thread *getParent(void)
01316 {return _parent;};
01317
01324 void suspend(void);
01325
01329 void resume(void);
01330
01337 inline Cancel getCancel(void)
01338 {return _cancel;};
01339
01346 bool isRunning(void);
01347
01353 bool isDetached(void);
01354
01358 void join(void);
01359
01366 bool isThread(void);
01367
01373 friend CCXX_EXPORT(Throw) getException(void);
01374
01380 friend CCXX_EXPORT(void) setException(Throw mode);
01381
01388 friend inline void operator++(Thread &th)
01389 {if (th._start) th._start->post();};
01390
01391 friend inline void operator--(Thread &th)
01392 {if (th._start) th._start->wait();};
01393
01394 #ifdef WIN32
01395
01396 bool isCancelled();
01397
01398 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01399 #endif
01400 };
01401
01407 CCXX_EXPORT(Thread*) getThread(void);
01409 CCXX_EXPORT(Thread::Throw) getException(void);
01411 CCXX_EXPORT(void) setException(Thread::Throw mode);
01412
01413 #if !defined(WIN32) && !defined(__MINGW32__)
01414 typedef int signo_t;
01415
01416 class PosixThread: public Thread
01417 {
01418 private:
01419 #ifndef WIN32
01420
01421 friend class ThreadImpl;
01422 friend class Thread;
01423 #endif
01424 #ifndef CCXX_SIG_THREAD_ALARM
01425 static PosixThread *_timer;
01426 static Mutex _arm;
01427 #endif
01428
01429 time_t _alarm;
01430 static void signalThread(Thread* th,signo_t signo);
01431 protected:
01432
01439 inline void signalParent(signo_t signo)
01440 { signalThread(_parent,signo); };
01441
01448 inline void signalMain(signo_t signo)
01449 { signalThread(_main,signo);};
01450
01455 virtual void onTimer(void)
01456 {return;};
01457
01462 virtual void onHangup(void)
01463 {return;};
01464
01469 virtual void onException(void)
01470 {return;};
01471
01476 virtual void onDisconnect(void)
01477 {return;};
01478
01483 virtual void onPolling(void)
01484 {return;};
01485
01492 virtual void onSignal(int)
01493 {return;};
01494
01507 void setTimer(timeout_t timer, bool periodic = false);
01508
01515 timeout_t getTimer(void) const;
01516
01522 void endTimer(void);
01523
01530 void waitSignal(signo_t signo);
01531
01538 void setSignal(int signo, bool active);
01539 public:
01540
01541 CCXX_MEMBER_EXPORT(CCXX_EMPTY) PosixThread(int pri = 0, size_t stack = 0);
01542
01548 inline void signalThread(int signo)
01549 {signalThread(this, signo);};
01550
01557 friend void sigInstall(int signo);
01558 };
01559 #endif
01560
01575 class ThreadKey
01576 {
01577 private:
01578 #ifndef WIN32
01579 pthread_key_t key;
01580 typedef void (*TDestruct)(void*);
01581 friend class ThreadImpl;
01582 ThreadKey(TDestruct destruct);
01583 #else
01584 DWORD key;
01585 #endif
01586
01587 public:
01591 ThreadKey();
01595 virtual ~ThreadKey();
01603 void *getKey(void);
01611 void setKey(void *);
01612 };
01613
01624 class CCXX_CLASS_EXPORT TimerPort
01625 {
01626 #ifndef WIN32
01627 struct timeval timer;
01628 #else
01629 DWORD timer;
01630 #endif
01631 bool active;
01632
01633 public:
01640 TimerPort();
01641
01650 void setTimer(timeout_t timeout = 0);
01651
01661 void incTimer(timeout_t timeout);
01662
01668 void endTimer(void);
01669
01681 timeout_t getTimer(void) const;
01682
01692 timeout_t getElapsed(void) const;
01693 };
01694
01696 inline int get(Buffer &b, void *o)
01697 {return b.wait(o);};
01698
01700 inline int put(Buffer &b, void *o)
01701 {return b.post(o);};
01702
01704 inline int peek(Buffer &b, void *o)
01705 {return b.peek(o);};
01706
01707
01708
01709 #if !defined(WIN32)
01710
01711
01712 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01713
01714 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01715 void wait(signo_t signo);
01716 #endif
01717
01718 #endif // !WIN32
01719
01720
01721 #ifndef WIN32
01722 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01723 #if defined(HAVE_SYS_STREAM_H)
01724 #if defined(__linux__)
01725 #define CCXX_USE_POLL 1
01726 #endif
01727 #else
01728 #define CCXX_USE_POLL 1
01729 #endif
01730 #endif
01731
01732 #ifdef CCXX_USE_POLL
01733
01741 class Poller
01742 {
01743 private:
01744 int nufds;
01745 pollfd *ufds;
01746
01747 public:
01748 Poller();
01749
01750 virtual ~Poller();
01751
01759 pollfd *getList(int cnt);
01760
01766 inline pollfd *getList(void)
01767 {return ufds;};
01768 };
01769 #endif
01770 #endif // !WIN32
01771
01772 #ifdef COMMON_STD_EXCEPTION
01773
01779 class ThrException : public Exception
01780 {
01781 public:
01782 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01783 };
01784
01791 class SyncException : public ThrException
01792 {
01793 public:
01794 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01795 };
01796
01797 class InterruptException : public ThrException
01798 {
01799 public:
01800 InterruptException() : ThrException("interrupted") {};
01801 };
01802
01803 #endif
01804
01805
01806
01807
01808
01809
01810
01811 #ifdef CCXX_NAMESPACES
01812 };
01813 #endif
01814
01815 #endif
01816