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
00044 #ifndef CCXX_THREAD_H_
00045 #define CCXX_THREAD_H_
00046
00047 #include <cc++/config.h>
00048
00049 #ifndef CCXX_STRING_H_
00050 #include <cc++/string.h>
00051 #endif
00052
00053 #ifndef WIN32
00054 #define CCXX_POSIX
00055 #endif // !WIN32
00056
00057 #include <ctime>
00058
00059 #ifndef WIN32
00060 #include <pthread.h>
00061 #endif // !WIN32
00062
00063 #undef CCXX_USE_WIN32_ATOMIC
00064 #ifndef WIN32
00065 #include <time.h>
00066 #include <signal.h>
00067 #include <unistd.h>
00068
00069 #ifdef _THR_UNIXWARE
00070 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00071 #endif
00072
00073 typedef pthread_t cctid_t;
00074 typedef unsigned long timeout_t;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #else // WIN32
00086 typedef DWORD cctid_t;
00087 typedef DWORD timeout_t;
00088
00089 #define MAX_SEM_VALUE 1000000
00090 #define CCXX_USE_WIN32_ATOMIC 1
00091
00092 #endif // !WIN32
00093
00094 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00095 #include <ios>
00096 #endif
00097
00098 #ifdef CCXX_NAMESPACES
00099 namespace ost {
00100 #ifdef __BORLANDC__
00101 # if __BORLANDC__ >= 0x0560
00102 using std::time_t;
00103 using std::tm;
00104 # endif
00105 #endif
00106 #endif
00107
00108 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00109 using namespace __gnu_cxx;
00110 #endif
00111
00112 class __EXPORT Thread;
00113 class __EXPORT ThreadKey;
00114
00115 #define TIMEOUT_INF ~((timeout_t) 0)
00116
00117 #define ENTER_CRITICAL enterMutex();
00118 #define LEAVE_CRITICAL leaveMutex();
00119 #define ENTER_DEFERRED setCancel(cancelDeferred);
00120 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00121
00122 #ifndef WIN32
00123
00124
00125
00126
00127
00128
00129 #undef sleep
00130 #define psleep(x) (sleep)(x)
00131
00132 #ifdef signal
00133 #undef signal
00134 #endif
00135
00136 #endif // !WIN32
00137
00138 #undef Yield
00139
00140 class __EXPORT Conditional;
00141 class __EXPORT Event;
00142
00186 class __EXPORT Mutex
00187 {
00188 private:
00189 static bool _debug;
00190 String _name;
00191 #ifndef WIN32
00192 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00193 int volatile _level;
00194 Thread *volatile _tid;
00195 #endif
00196
00197
00198
00199
00200
00201
00202
00203
00204 pthread_mutex_t _mutex;
00205 #else // WIN32
00206
00207 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00208 # error "Can't determine underground for Mutex"
00209 # endif
00210
00211 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00212 HANDLE _mutex;
00213 #endif
00214 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00215 CRITICAL_SECTION _criticalSection;
00216 #endif
00217
00218 #endif // WIN32
00219
00220 public:
00226 Mutex(const char *name = NULL);
00227
00233 virtual ~Mutex();
00234
00240 static void setDebug(bool mode)
00241 {_debug = mode;};
00242
00248 inline void nameMutex(const char *name)
00249 {_name = name;};
00250
00258 void enterMutex(void);
00259
00263 inline void enter(void)
00264 {enterMutex();};
00265
00269 inline void leave(void)
00270 {leaveMutex();};
00271
00277 inline bool test(void)
00278 {return tryEnterMutex();};
00279
00290 bool tryEnterMutex(void);
00291
00302 void leaveMutex(void);
00303 };
00304
00328 class __EXPORT MutexLock
00329 {
00330 private:
00331 Mutex& mutex;
00332 public:
00338 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00339 { mutex.enterMutex(); }
00340
00344
00345 ~MutexLock()
00346 { mutex.leaveMutex(); }
00347 };
00348
00357 class __EXPORT ThreadLock
00358 {
00359 private:
00360 #ifdef HAVE_PTHREAD_RWLOCK
00361 pthread_rwlock_t _lock;
00362 #else
00363 Mutex mutex;
00364 #endif
00365
00366 public:
00370 ThreadLock();
00371
00375 virtual ~ThreadLock();
00376
00380 void readLock(void);
00381
00385 void writeLock(void);
00386
00392 bool tryReadLock(void);
00393
00399 bool tryWriteLock(void);
00400
00404 void unlock(void);
00405 };
00406
00427 class __EXPORT ReadLock
00428 {
00429 private:
00430 ThreadLock& tl;
00431
00432 public:
00438 ReadLock( ThreadLock& _tl ) : tl( _tl )
00439 { tl.readLock(); }
00443
00444 ~ReadLock()
00445 { tl.unlock(); }
00446 };
00447
00468 class __EXPORT WriteLock
00469 {
00470 private:
00471 ThreadLock& tl;
00472
00473 public:
00479 WriteLock( ThreadLock& _tl ) : tl( _tl )
00480 { tl.writeLock(); }
00484
00485 ~WriteLock()
00486 { tl.unlock(); }
00487 };
00488
00489
00499 class __EXPORT MutexCounter : public Mutex
00500 {
00501 private:
00502 volatile int counter;
00503
00504 public:
00510 MutexCounter(const char *id = NULL);
00511
00519 MutexCounter(int initial, const char *id = NULL);
00520
00521 friend __EXPORT int operator++(MutexCounter &mc);
00522 friend __EXPORT int operator--(MutexCounter &mc);
00523 };
00524
00535 class __EXPORT AtomicCounter
00536 {
00537 #ifndef CCXX_USE_WIN32_ATOMIC
00538 private:
00539 #if defined(HAVE_ATOMIC_AIX)
00540 volatile int counter;
00541 #elif defined(HAVE_GCC_BITS_ATOMIC)
00542 volatile _Atomic_word counter;
00543 #elif defined(HAVE_GCC_CXX_BITS_ATOMIC)
00544 volatile _Atomic_word counter;
00545
00546 #elif defined(HAVE_ATOMIC)
00547 atomic_t atomic;
00548 #else
00549 volatile int counter;
00550 pthread_mutex_t _mutex;
00551 #endif
00552
00553 public:
00557 AtomicCounter();
00558
00564 AtomicCounter(int value);
00565
00566 ~AtomicCounter();
00567
00568 int operator++(void);
00569 int operator--(void);
00570 int operator+=(int change);
00571 int operator-=(int change);
00572 int operator+(int change);
00573 int operator-(int change);
00574 int operator=(int value);
00575 bool operator!(void);
00576 operator int();
00577 #else
00578 private:
00579 long atomic;
00580
00581 public:
00582 inline AtomicCounter()
00583 {atomic = 0;};
00584
00585 inline AtomicCounter(int value)
00586 {atomic = value;};
00587
00588 inline int operator++(void)
00589 {return InterlockedIncrement(&atomic);};
00590
00591 inline int operator--(void)
00592 {return InterlockedDecrement(&atomic);};
00593
00594 int operator+=(int change);
00595
00596 int operator-=(int change);
00597
00598 inline int operator+(int change)
00599 {return atomic + change;};
00600
00601 inline int operator-(int change)
00602 {return atomic - change;};
00603
00604 inline int operator=(int value)
00605 {return InterlockedExchange(&atomic, value);};
00606
00607 inline bool operator!(void)
00608 {return (atomic == 0) ? true : false;};
00609
00610 inline operator int()
00611 {return atomic;};
00612 #endif
00613 };
00614
00615 #ifndef WIN32
00616
00636 class __EXPORT Conditional
00637 {
00638 private:
00639 pthread_cond_t _cond;
00640 pthread_mutex_t _mutex;
00641
00642 public:
00648 Conditional(const char *id = NULL);
00649
00653 virtual ~Conditional();
00654
00660 void signal(bool broadcast);
00661
00668 bool wait(timeout_t timer = 0, bool locked = false);
00669
00676 void enterMutex(void);
00677
00686 inline void lock(void)
00687 {enterMutex();};
00688
00699 bool tryEnterMutex(void);
00700
00701 inline bool test(void)
00702 {return tryEnterMutex();};
00703
00709 void leaveMutex(void);
00710
00711 inline void unlock(void)
00712 {return leaveMutex();};
00713 };
00714 #endif
00715
00733 class __EXPORT Semaphore
00734 {
00735 private:
00736 #ifndef WIN32
00737 unsigned _count, _waiters;
00738 pthread_mutex_t _mutex;
00739 pthread_cond_t _cond;
00740 #else
00741 HANDLE semObject;
00742 #endif // !WIN32
00743
00744 public:
00753 Semaphore(unsigned resource = 0);
00754
00761 virtual ~Semaphore();
00762
00778 bool wait(timeout_t timeout = 0);
00779
00791 void post(void);
00792
00793 #ifndef WIN32
00794
00802 void force_unlock_after_cancellation();
00803
00804 #endif // WIN32
00805
00806
00807
00808 #if 0
00809
00814 int getValue(void);
00815 #endif
00816 };
00817
00837 class __EXPORT SemaphoreLock
00838 {
00839 private:
00840 Semaphore& sem;
00841
00842 public:
00846 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00847 { sem.wait(); }
00851
00852 ~SemaphoreLock()
00853 { sem.post(); }
00854 };
00855
00869 class __EXPORT Event
00870 {
00871 private:
00872 #ifndef WIN32
00873 pthread_mutex_t _mutex;
00874 pthread_cond_t _cond;
00875 bool _signaled;
00876 int _count;
00877 #else
00878 HANDLE cond;
00879 #endif
00880
00881 public:
00882 Event();
00883
00884 virtual ~Event();
00885
00892 void reset(void);
00893
00897 void signal(void);
00898
00907 bool wait(timeout_t timer);
00908 bool wait(void);
00909 };
00910
00911
01093 class __EXPORT Thread
01094 {
01095 public:
01099 typedef enum Throw {
01100 throwNothing,
01101 throwObject,
01102 throwException
01103 } Throw;
01104
01108 typedef enum Cancel {
01109 cancelInitial=0,
01110 cancelDeferred=1,
01111 cancelImmediate,
01112 cancelDisabled,
01113 cancelManual,
01115 cancelDefault=cancelDeferred
01117 } Cancel;
01118
01122 typedef enum Suspend {
01123 suspendEnable,
01124 suspendDisable
01125 } Suspend;
01126
01127 #ifndef WIN32
01128
01129 friend class PosixThread;
01130 #endif
01131
01132 friend class DummyThread;
01133 private:
01134 friend class Cancellation;
01135 friend class postream_type;
01136 friend class Slog;
01137
01138 Semaphore joinSem;
01139 static Thread* _main;
01140
01141 Thread *_parent;
01142 Cancel _cancel;
01143 Semaphore *_start;
01144
01145
01146 friend class ThreadImpl;
01147 class ThreadImpl* priv;
01148
01149 public:
01150 static Thread *get(void);
01151
01152 private:
01153 #ifdef WIN32
01154 static unsigned __stdcall Execute(Thread *th);
01155 #endif
01156
01157
01158 void close();
01159
01160 private:
01161 char _name[32];
01162 static size_t _autostack;
01163
01164 #ifdef WIN32
01165 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01166 #endif
01167
01168 protected:
01176 void setName(const char *text);
01177
01187 virtual void run(void) = 0;
01188
01210 virtual void final(void);
01211
01223 virtual void initial(void);
01224
01234 virtual void* getExtended(void);
01235
01243 virtual void notify(Thread*);
01244
01250 void exit(void);
01251
01255 void sync(void);
01256
01260 bool testCancel(void);
01261
01271 void setCancel(Cancel mode);
01272
01280 void setSuspend(Suspend mode);
01281
01290 void terminate(void);
01291
01295 inline void clrParent(void)
01296 {_parent = NULL;};
01297
01298 public:
01307 Thread(bool isMain);
01308
01320 Thread(int pri = 0, size_t stack = 0);
01321
01322 #ifndef WIN32
01323
01331 Thread(const Thread &th);
01332 #endif
01333
01340 virtual ~Thread();
01341
01347 static void setStack(size_t size = 0)
01348 {_autostack = size;};
01349
01359 static void sleep(timeout_t msec);
01360
01365 static void yield(void);
01366
01379 int start(Semaphore *start = 0);
01380
01389 int detach(Semaphore *start = 0);
01390
01397 inline Thread *getParent(void)
01398 {return _parent;};
01399
01406 void suspend(void);
01407
01411 void resume(void);
01412
01419 inline Cancel getCancel(void)
01420 {return _cancel;};
01421
01428 bool isRunning(void) const;
01429
01435 bool isDetached(void) const;
01436
01440 void join(void);
01441
01448 bool isThread(void) const;
01449
01455 cctid_t getId(void) const;
01456
01463 const char *getName(void) const
01464 {return _name;};
01465
01471 static Throw getException(void);
01472
01478 static void setException(Throw mode);
01479
01486 friend inline void operator++(Thread &th)
01487 {if (th._start) th._start->post();};
01488
01489 friend inline void operator--(Thread &th)
01490 {if (th._start) th._start->wait();};
01491
01492 #ifdef WIN32
01493 bool isCancelled() const;
01494
01495 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01496 #endif
01497
01505 static Cancel enterCancel(void);
01506
01512 static void exitCancel(Cancel cancel);
01513 };
01514
01524 class __EXPORT Cancellation
01525 {
01526 private:
01527 Thread::Cancel prior;
01528
01529 public:
01530 Cancellation(Thread::Cancel cancel);
01531 ~Cancellation();
01532 };
01533
01534 #if !defined(WIN32) && !defined(__MINGW32__)
01535 typedef int signo_t;
01536
01537 class PosixThread: public Thread
01538 {
01539 private:
01540 #ifndef WIN32
01541
01542 friend class ThreadImpl;
01543 friend class Thread;
01544 #endif
01545 #ifndef CCXX_SIG_THREAD_ALARM
01546 static PosixThread *_timer;
01547 static Mutex _arm;
01548 #endif
01549
01550 time_t _alarm;
01551 static void signalThread(Thread* th,signo_t signo);
01552 protected:
01553
01560 inline void signalParent(signo_t signo)
01561 { signalThread(_parent,signo); };
01562
01569 inline void signalMain(signo_t signo)
01570 { signalThread(_main,signo);};
01571
01576 virtual void onTimer(void);
01577
01582 virtual void onHangup(void);
01583
01588 virtual void onException(void);
01589
01594 virtual void onDisconnect(void);
01595
01600 virtual void onPolling(void);
01601
01608 virtual void onSignal(int);
01609
01622 void setTimer(timeout_t timer, bool periodic = false);
01623
01630 timeout_t getTimer(void) const;
01631
01637 void endTimer(void);
01638
01639 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01640
01646 void waitSignal(signo_t signo);
01647 #endif
01648
01655 void setSignal(int signo, bool active);
01656
01663 pthread_attr_t *getPthreadAttrPtr(void);
01664
01669 pthread_t getPthreadId(void);
01670
01671 public:
01672
01673 PosixThread(int pri = 0, size_t stack = 0);
01674
01680 inline void signalThread(int signo)
01681 {signalThread(this, signo);};
01682
01689 static void sigInstall(int signo);
01690 };
01691 #endif
01692
01707 class __EXPORT ThreadKey
01708 {
01709 private:
01710 #ifndef WIN32
01711 pthread_key_t key;
01712 typedef void (*TDestruct)(void*);
01713 friend class ThreadImpl;
01714 ThreadKey(TDestruct destruct);
01715 #else
01716 DWORD key;
01717 #endif
01718
01719 public:
01723 ThreadKey();
01724
01728 virtual ~ThreadKey();
01729
01737 void *getKey(void);
01738
01746 void setKey(void *);
01747 };
01748
01759 class __EXPORT TimerPort
01760 {
01761 #ifndef WIN32
01762 struct timeval timer;
01763 #else
01764 DWORD timer;
01765 #endif
01766 bool active;
01767
01768 public:
01775 TimerPort();
01776
01785 void setTimer(timeout_t timeout = 0);
01786
01796 void incTimer(timeout_t timeout);
01797
01807 void decTimer(timeout_t timeout);
01808
01813 void sleepTimer(void);
01814
01820 void endTimer(void);
01821
01833 timeout_t getTimer(void) const;
01834
01844 timeout_t getElapsed(void) const;
01845 };
01846
01847
01848
01849
01850 #if !defined(WIN32)
01851
01852
01853 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01854
01855 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01856 void wait(signo_t signo);
01857 #endif
01858
01859 #endif // !WIN32
01860
01861 #ifdef USE_POLL
01862
01870 class Poller
01871 {
01872 private:
01873 int nufds;
01874 pollfd *ufds;
01875
01876 public:
01877 Poller();
01878
01879 virtual ~Poller();
01880
01888 pollfd *getList(int cnt);
01889
01895 inline pollfd *getList(void)
01896 {return ufds;};
01897 };
01898 #endif
01899
01900 inline Thread *getThread(void)
01901 {return Thread::get();}
01902
01932 class __EXPORT SysTime
01933 {
01934 private:
01935 static Mutex timeLock;
01936
01937 protected:
01938 inline static void lock(void)
01939 {timeLock.enterMutex();}
01940
01941 inline static void unlock(void)
01942 {timeLock.leaveMutex();}
01943
01944 public:
01945 static time_t getTime(time_t *tloc = NULL);
01946 static time_t time(time_t *tloc)
01947 { return getTime(tloc); };
01948
01949 static int getTimeOfDay(struct timeval *tp);
01950 static int gettimeofday(struct timeval *tp, struct timezone *)
01951 { return getTimeOfDay(tp); };
01952
01953 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01954 static struct tm *locatime(const time_t *clock, struct tm *result)
01955 { return getLocalTime(clock, result); };
01956
01957 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01958 static struct tm *gmtime(const time_t *clock, struct tm *result)
01959 { return getGMTTime(clock, result);};
01960 };
01961
01962 #ifndef HAVE_LOCALTIME_R
01963
01964 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01965 {return SysTime::getLocalTime(t, b);};
01966 inline char *ctime_r(const time_t *t, char *buf)
01967 {return ctime(t);};
01968 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01969 {return SysTime::getGMTTime(t, b);};
01970 inline char *asctime_r(const struct tm *tm, char *b) \
01971 {return asctime(tm);};
01972
01973 #endif
01974
01975 #ifdef CCXX_NAMESPACES
01976 }
01977 #endif
01978
01979 #endif
01980