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
00043 #ifndef CCXX_THREAD_H_
00044 #define CCXX_THREAD_H_
00045
00046 #include <cc++/config.h>
00047
00048 #ifndef WIN32
00049 #define CCXX_POSIX
00050 #endif // !WIN32
00051
00052 #include <ctime>
00053
00054 #ifndef WIN32
00055 #include <pthread.h>
00056 #endif // !WIN32
00057
00058 #undef CCXX_USE_WIN32_ATOMIC
00059 #ifndef WIN32
00060 #include <time.h>
00061 #include <signal.h>
00062 #include <unistd.h>
00063
00064 #ifdef _THR_UNIXWARE
00065 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00066 #endif
00067
00068 typedef pthread_t cctid_t;
00069 typedef unsigned long timeout_t;
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #else // WIN32
00081 typedef DWORD cctid_t;
00082 typedef DWORD timeout_t;
00083
00084 #define MAX_SEM_VALUE 1000000
00085 #define CCXX_USE_WIN32_ATOMIC 1
00086
00087 #endif // !WIN32
00088
00089 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00090 #include <ios>
00091 #endif
00092
00093 #ifdef CCXX_NAMESPACES
00094 namespace ost {
00095 #ifdef __BORLANDC__
00096 # if __BORLANDC__ >= 0x0560
00097 using std::time_t;
00098 using std::tm;
00099 # endif
00100 #endif
00101 #endif
00102
00103 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00104 using namespace __gnu_cxx;
00105 #endif
00106
00107 class __EXPORT Thread;
00108 class __EXPORT ThreadKey;
00109
00110 #define TIMEOUT_INF ~((timeout_t) 0)
00111
00112 #define ENTER_CRITICAL enterMutex();
00113 #define LEAVE_CRITICAL leaveMutex();
00114 #define ENTER_DEFERRED setCancel(cancelDeferred);
00115 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00116
00117 #ifndef WIN32
00118
00119
00120
00121
00122
00123
00124 #undef sleep
00125 #define psleep(x) (sleep)(x)
00126
00127 #ifdef signal
00128 #undef signal
00129 #endif
00130
00131 #endif // !WIN32
00132
00133 #undef Yield
00134
00135 class __EXPORT Conditional;
00136 class __EXPORT Event;
00137
00181 class __EXPORT Mutex
00182 {
00183 private:
00184 static bool _debug;
00185 const char *_name;
00186 #ifndef WIN32
00187 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00188 int volatile _level;
00189 Thread *volatile _tid;
00190 #endif
00191
00192
00193
00194
00195
00196
00197
00198
00199 pthread_mutex_t _mutex;
00200 #else // WIN32
00201
00202 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00203 # error "Can't determine underground for Mutex"
00204 # endif
00205
00206 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00207 HANDLE _mutex;
00208 #endif
00209 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00210 CRITICAL_SECTION _criticalSection;
00211 #endif
00212
00213 #endif // WIN32
00214
00215 public:
00221 Mutex(const char *name = NULL);
00222
00228 virtual ~Mutex();
00229
00235 static void setDebug(bool mode)
00236 {_debug = mode;};
00237
00243 inline void nameMutex(const char *name)
00244 {_name = name;};
00245
00253 void enterMutex(void);
00254
00258 inline void enter(void)
00259 {enterMutex();};
00260
00264 inline void leave(void)
00265 {leaveMutex();};
00266
00272 inline bool test(void)
00273 {return tryEnterMutex();};
00274
00285 bool tryEnterMutex(void);
00286
00297 void leaveMutex(void);
00298 };
00299
00323 class __EXPORT MutexLock
00324 {
00325 private:
00326 Mutex& mutex;
00327 public:
00333 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00334 { mutex.enterMutex(); }
00335
00339
00340 ~MutexLock()
00341 { mutex.leaveMutex(); }
00342 };
00343
00352 class __EXPORT ThreadLock
00353 {
00354 private:
00355 #ifdef HAVE_PTHREAD_RWLOCK
00356 pthread_rwlock_t _lock;
00357 #else
00358 Mutex mutex;
00359 #endif
00360
00361 public:
00365 ThreadLock();
00366
00370 virtual ~ThreadLock();
00371
00375 void readLock(void);
00376
00380 void writeLock(void);
00381
00387 bool tryReadLock(void);
00388
00394 bool tryWriteLock(void);
00395
00399 void unlock(void);
00400 };
00401
00422 class __EXPORT ReadLock
00423 {
00424 private:
00425 ThreadLock& tl;
00426
00427 public:
00433 ReadLock( ThreadLock& _tl ) : tl( _tl )
00434 { tl.readLock(); }
00438
00439 ~ReadLock()
00440 { tl.unlock(); }
00441 };
00442
00463 class __EXPORT WriteLock
00464 {
00465 private:
00466 ThreadLock& tl;
00467
00468 public:
00474 WriteLock( ThreadLock& _tl ) : tl( _tl )
00475 { tl.writeLock(); }
00479
00480 ~WriteLock()
00481 { tl.unlock(); }
00482 };
00483
00484
00494 class __EXPORT MutexCounter : public Mutex
00495 {
00496 private:
00497 volatile int counter;
00498
00499 public:
00505 MutexCounter(const char *id = NULL);
00506
00514 MutexCounter(int initial, const char *id = NULL);
00515
00516 friend __EXPORT int operator++(MutexCounter &mc);
00517 friend __EXPORT int operator--(MutexCounter &mc);
00518 };
00519
00530 class __EXPORT AtomicCounter
00531 {
00532 #ifndef CCXX_USE_WIN32_ATOMIC
00533 private:
00534 #if defined(HAVE_ATOMIC_AIX)
00535 volatile int counter;
00536 #elif defined(HAVE_GCC_BITS_ATOMIC)
00537 volatile _Atomic_word counter;
00538 #elif defined(HAVE_GCC_CXX_BITS_ATOMIC)
00539 volatile _Atomic_word counter;
00540
00541 #elif defined(HAVE_ATOMIC)
00542 atomic_t atomic;
00543 #else
00544 volatile int counter;
00545 pthread_mutex_t _mutex;
00546 #endif
00547
00548 public:
00552 AtomicCounter();
00553
00559 AtomicCounter(int value);
00560
00561 ~AtomicCounter();
00562
00563 int operator++(void);
00564 int operator--(void);
00565 int operator+=(int change);
00566 int operator-=(int change);
00567 int operator+(int change);
00568 int operator-(int change);
00569 int operator=(int value);
00570 bool operator!(void);
00571 operator int();
00572 #else
00573 private:
00574 long atomic;
00575
00576 public:
00577 inline AtomicCounter()
00578 {atomic = 0;};
00579
00580 inline AtomicCounter(int value)
00581 {atomic = value;};
00582
00583 inline int operator++(void)
00584 {return InterlockedIncrement(&atomic);};
00585
00586 inline int operator--(void)
00587 {return InterlockedDecrement(&atomic);};
00588
00589 int operator+=(int change);
00590
00591 int operator-=(int change);
00592
00593 inline int operator+(int change)
00594 {return atomic + change;};
00595
00596 inline int operator-(int change)
00597 {return atomic - change;};
00598
00599 inline int operator=(int value)
00600 {return InterlockedExchange(&atomic, value);};
00601
00602 inline bool operator!(void)
00603 {return (atomic == 0) ? true : false;};
00604
00605 inline operator int()
00606 {return atomic;};
00607 #endif
00608 };
00609
00610 #ifndef WIN32
00611
00631 class __EXPORT Conditional
00632 {
00633 private:
00634 pthread_cond_t _cond;
00635 pthread_mutex_t _mutex;
00636
00637 public:
00643 Conditional(const char *id = NULL);
00644
00648 virtual ~Conditional();
00649
00655 void signal(bool broadcast);
00656
00663 bool wait(timeout_t timer = 0, bool locked = false);
00664
00671 void enterMutex(void);
00672
00681 inline void lock(void)
00682 {enterMutex();};
00683
00694 bool tryEnterMutex(void);
00695
00696 inline bool test(void)
00697 {return tryEnterMutex();};
00698
00704 void leaveMutex(void);
00705
00706 inline void unlock(void)
00707 {return leaveMutex();};
00708 };
00709 #endif
00710
00728 class __EXPORT Semaphore
00729 {
00730 private:
00731 #ifndef WIN32
00732 unsigned _count, _waiters;
00733 pthread_mutex_t _mutex;
00734 pthread_cond_t _cond;
00735 #else
00736 HANDLE semObject;
00737 #endif // !WIN32
00738
00739 public:
00748 Semaphore(unsigned resource = 0);
00749
00756 virtual ~Semaphore();
00757
00773 bool wait(timeout_t timeout = 0);
00774
00786 void post(void);
00787
00788
00789
00790
00791 #if 0
00792
00797 int getValue(void);
00798 #endif
00799 };
00800
00820 class __EXPORT SemaphoreLock
00821 {
00822 private:
00823 Semaphore& sem;
00824
00825 public:
00829 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00830 { sem.wait(); }
00834
00835 ~SemaphoreLock()
00836 { sem.post(); }
00837 };
00838
00852 class __EXPORT Event
00853 {
00854 private:
00855 #ifndef WIN32
00856 pthread_mutex_t _mutex;
00857 pthread_cond_t _cond;
00858 bool _signaled;
00859 int _count;
00860 #else
00861 HANDLE cond;
00862 #endif
00863
00864 public:
00865 Event();
00866
00867 virtual ~Event();
00868
00875 void reset(void);
00876
00880 void signal(void);
00881
00890 bool wait(timeout_t timer);
00891 bool wait(void);
00892 };
00893
00894
01076 class __EXPORT Thread
01077 {
01078 public:
01082 typedef enum Throw {
01083 throwNothing,
01084 throwObject,
01085 throwException
01086 } Throw;
01087
01091 typedef enum Cancel {
01092 cancelInitial=0,
01093 cancelDeferred=1,
01094 cancelImmediate,
01095 cancelDisabled,
01096 cancelManual,
01098 cancelDefault=cancelDeferred
01100 } Cancel;
01101
01105 typedef enum Suspend {
01106 suspendEnable,
01107 suspendDisable
01108 } Suspend;
01109
01110 #ifndef WIN32
01111
01112 friend class PosixThread;
01113 #endif
01114
01115 friend class DummyThread;
01116 private:
01117 friend class Cancellation;
01118 friend class postream_type;
01119 friend class Slog;
01120
01121 Semaphore joinSem;
01122 static Thread* _main;
01123
01124 Thread *_parent;
01125 Cancel _cancel;
01126 Semaphore *_start;
01127
01128
01129 friend class ThreadImpl;
01130 class ThreadImpl* priv;
01131
01132 public:
01133 static Thread *get(void);
01134
01135 private:
01136 #ifdef WIN32
01137 static unsigned __stdcall Execute(Thread *th);
01138 #endif
01139
01140
01141 void close();
01142
01143 private:
01144 char _name[32];
01145 static size_t _autostack;
01146
01147 #ifdef WIN32
01148 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01149 #endif
01150
01151 protected:
01159 void setName(const char *text);
01160
01170 virtual void run(void) = 0;
01171
01193 virtual void final(void);
01194
01206 virtual void initial(void);
01207
01217 virtual void* getExtended(void);
01218
01226 virtual void notify(Thread*);
01227
01233 void exit(void);
01234
01238 void sync(void);
01239
01243 bool testCancel(void);
01244
01254 void setCancel(Cancel mode);
01255
01263 void setSuspend(Suspend mode);
01264
01273 void terminate(void);
01274
01278 inline void clrParent(void)
01279 {_parent = NULL;};
01280
01281 public:
01290 Thread(bool isMain);
01291
01303 Thread(int pri = 0, size_t stack = 0);
01304
01305 #ifndef WIN32
01306
01314 Thread(const Thread &th);
01315 #endif
01316
01323 virtual ~Thread();
01324
01330 static void setStack(size_t size = 0)
01331 {_autostack = size;};
01332
01342 static void sleep(timeout_t msec);
01343
01348 static void yield(void);
01349
01362 int start(Semaphore *start = 0);
01363
01372 int detach(Semaphore *start = 0);
01373
01380 inline Thread *getParent(void)
01381 {return _parent;};
01382
01389 void suspend(void);
01390
01394 void resume(void);
01395
01402 inline Cancel getCancel(void)
01403 {return _cancel;};
01404
01411 bool isRunning(void) const;
01412
01418 bool isDetached(void) const;
01419
01423 void join(void);
01424
01431 bool isThread(void) const;
01432
01438 cctid_t getId(void) const;
01439
01446 const char *getName(void) const
01447 {return _name;};
01448
01454 static Throw getException(void);
01455
01461 static void setException(Throw mode);
01462
01469 friend inline void operator++(Thread &th)
01470 {if (th._start) th._start->post();};
01471
01472 friend inline void operator--(Thread &th)
01473 {if (th._start) th._start->wait();};
01474
01475 #ifdef WIN32
01476 bool isCancelled() const;
01477
01478 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01479 #endif
01480
01488 static Cancel enterCancel(void);
01489
01495 static void exitCancel(Cancel cancel);
01496 };
01497
01507 class __EXPORT Cancellation
01508 {
01509 private:
01510 Thread::Cancel prior;
01511
01512 public:
01513 Cancellation(Thread::Cancel cancel);
01514 ~Cancellation();
01515 };
01516
01517 #if !defined(WIN32) && !defined(__MINGW32__)
01518 typedef int signo_t;
01519
01520 class PosixThread: public Thread
01521 {
01522 private:
01523 #ifndef WIN32
01524
01525 friend class ThreadImpl;
01526 friend class Thread;
01527 #endif
01528 #ifndef CCXX_SIG_THREAD_ALARM
01529 static PosixThread *_timer;
01530 static Mutex _arm;
01531 #endif
01532
01533 time_t _alarm;
01534 static void signalThread(Thread* th,signo_t signo);
01535 protected:
01536
01543 inline void signalParent(signo_t signo)
01544 { signalThread(_parent,signo); };
01545
01552 inline void signalMain(signo_t signo)
01553 { signalThread(_main,signo);};
01554
01559 virtual void onTimer(void);
01560
01565 virtual void onHangup(void);
01566
01571 virtual void onException(void);
01572
01577 virtual void onDisconnect(void);
01578
01583 virtual void onPolling(void);
01584
01591 virtual void onSignal(int);
01592
01605 void setTimer(timeout_t timer, bool periodic = false);
01606
01613 timeout_t getTimer(void) const;
01614
01620 void endTimer(void);
01621
01622 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01623
01629 void waitSignal(signo_t signo);
01630 #endif
01631
01638 void setSignal(int signo, bool active);
01639
01646 pthread_attr_t *getPthreadAttrPtr(void);
01647
01652 pthread_t getPthreadId(void);
01653
01654 public:
01655
01656 PosixThread(int pri = 0, size_t stack = 0);
01657
01663 inline void signalThread(int signo)
01664 {signalThread(this, signo);};
01665
01672 static void sigInstall(int signo);
01673 };
01674 #endif
01675
01690 class __EXPORT ThreadKey
01691 {
01692 private:
01693 #ifndef WIN32
01694 pthread_key_t key;
01695 typedef void (*TDestruct)(void*);
01696 friend class ThreadImpl;
01697 ThreadKey(TDestruct destruct);
01698 #else
01699 DWORD key;
01700 #endif
01701
01702 public:
01706 ThreadKey();
01707
01711 virtual ~ThreadKey();
01712
01720 void *getKey(void);
01721
01729 void setKey(void *);
01730 };
01731
01742 class __EXPORT TimerPort
01743 {
01744 #ifndef WIN32
01745 struct timeval timer;
01746 #else
01747 DWORD timer;
01748 #endif
01749 bool active;
01750
01751 public:
01758 TimerPort();
01759
01768 void setTimer(timeout_t timeout = 0);
01769
01779 void incTimer(timeout_t timeout);
01780
01790 void decTimer(timeout_t timeout);
01791
01796 void sleepTimer(void);
01797
01803 void endTimer(void);
01804
01816 timeout_t getTimer(void) const;
01817
01827 timeout_t getElapsed(void) const;
01828 };
01829
01830
01831
01832
01833 #if !defined(WIN32)
01834
01835
01836 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01837
01838 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01839 void wait(signo_t signo);
01840 #endif
01841
01842 #endif // !WIN32
01843
01844 #ifdef USE_POLL
01845
01853 class Poller
01854 {
01855 private:
01856 int nufds;
01857 pollfd *ufds;
01858
01859 public:
01860 Poller();
01861
01862 virtual ~Poller();
01863
01871 pollfd *getList(int cnt);
01872
01878 inline pollfd *getList(void)
01879 {return ufds;};
01880 };
01881 #endif
01882
01883 inline Thread *getThread(void)
01884 {return Thread::get();}
01885
01915 class __EXPORT SysTime
01916 {
01917 private:
01918 static Mutex timeLock;
01919
01920 protected:
01921 inline static void lock(void)
01922 {timeLock.enterMutex();}
01923
01924 inline static void unlock(void)
01925 {timeLock.leaveMutex();}
01926
01927 public:
01928 static time_t getTime(time_t *tloc = NULL);
01929 static time_t time(time_t *tloc)
01930 { return getTime(tloc); };
01931
01932 static int getTimeOfDay(struct timeval *tp);
01933 static int gettimeofday(struct timeval *tp, struct timezone *)
01934 { return getTimeOfDay(tp); };
01935
01936 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01937 static struct tm *locatime(const time_t *clock, struct tm *result)
01938 { return getLocalTime(clock, result); };
01939
01940 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01941 static struct tm *gmtime(const time_t *clock, struct tm *result)
01942 { return getGMTTime(clock, result);};
01943 };
01944
01945 #ifndef HAVE_LOCALTIME_R
01946
01947 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01948 {return SysTime::getLocalTime(t, b);};
01949 inline char *ctime_r(const time_t *t, char *buf)
01950 {return ctime(t);};
01951 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01952 {return SysTime::getGMTTime(t, b);};
01953 inline char *asctime_r(const struct tm *tm, char *b) \
01954 {return asctime(tm);};
01955
01956 #endif
01957
01958 #ifdef CCXX_NAMESPACES
01959 }
01960 #endif
01961
01962 #endif
01963