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 CCXX_STRING_H_
00049 #include <cc++/string.h>
00050 #endif
00051
00052 #ifndef WIN32
00053 #define CCXX_POSIX
00054 #endif // !WIN32
00055
00056 #include <ctime>
00057
00058 #ifndef WIN32
00059 #include <pthread.h>
00060 #endif // !WIN32
00061
00062 #undef CCXX_USE_WIN32_ATOMIC
00063 #ifndef WIN32
00064 #include <time.h>
00065 #include <signal.h>
00066 #include <unistd.h>
00067
00068 #ifdef _THR_UNIXWARE
00069 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00070 #endif
00071
00072 typedef pthread_t cctid_t;
00073 typedef unsigned long timeout_t;
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #else // WIN32
00085 typedef DWORD cctid_t;
00086 typedef DWORD timeout_t;
00087
00088 #define MAX_SEM_VALUE 1000000
00089 #define CCXX_USE_WIN32_ATOMIC 1
00090
00091 #endif // !WIN32
00092
00093 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00094 #include <ios>
00095 #endif
00096
00097 #ifdef CCXX_NAMESPACES
00098 namespace ost {
00099 #ifdef __BORLANDC__
00100 # if __BORLANDC__ >= 0x0560
00101 using std::time_t;
00102 using std::tm;
00103 # endif
00104 #endif
00105 #endif
00106
00107 #ifdef HAVE_GCC_CXX_BITS_ATOMIC
00108 using namespace __gnu_cxx;
00109 #endif
00110
00111 class __EXPORT Thread;
00112 class __EXPORT ThreadKey;
00113
00114 #define TIMEOUT_INF ~((timeout_t) 0)
00115
00116 #define ENTER_CRITICAL enterMutex();
00117 #define LEAVE_CRITICAL leaveMutex();
00118 #define ENTER_DEFERRED setCancel(cancelDeferred);
00119 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00120
00121 #ifndef WIN32
00122
00123
00124
00125
00126
00127
00128 #undef sleep
00129 #define psleep(x) (sleep)(x)
00130
00131 #ifdef signal
00132 #undef signal
00133 #endif
00134
00135 #endif // !WIN32
00136
00137 #undef Yield
00138
00139 class __EXPORT Conditional;
00140 class __EXPORT Event;
00141
00185 class __EXPORT Mutex
00186 {
00187 private:
00188 static bool _debug;
00189 String _name;
00190 #ifndef WIN32
00191 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00192 int volatile _level;
00193 Thread *volatile _tid;
00194 #endif
00195
00196
00197
00198
00199
00200
00201
00202
00203 pthread_mutex_t _mutex;
00204 #else // WIN32
00205
00206 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00207 # error "Can't determine underground for Mutex"
00208 # endif
00209
00210 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00211 HANDLE _mutex;
00212 #endif
00213 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00214 CRITICAL_SECTION _criticalSection;
00215 #endif
00216
00217 #endif // WIN32
00218
00219 public:
00225 Mutex(const char *name = NULL);
00226
00232 virtual ~Mutex();
00233
00239 static void setDebug(bool mode)
00240 {_debug = mode;};
00241
00247 inline void nameMutex(const char *name)
00248 {_name = name;};
00249
00257 void enterMutex(void);
00258
00262 inline void enter(void)
00263 {enterMutex();};
00264
00268 inline void leave(void)
00269 {leaveMutex();};
00270
00276 inline bool test(void)
00277 {return tryEnterMutex();};
00278
00289 bool tryEnterMutex(void);
00290
00301 void leaveMutex(void);
00302 };
00303
00327 class __EXPORT MutexLock
00328 {
00329 private:
00330 Mutex& mutex;
00331 public:
00337 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00338 { mutex.enterMutex(); }
00339
00343
00344 ~MutexLock()
00345 { mutex.leaveMutex(); }
00346 };
00347
00356 class __EXPORT ThreadLock
00357 {
00358 private:
00359 #ifdef HAVE_PTHREAD_RWLOCK
00360 pthread_rwlock_t _lock;
00361 #else
00362 Mutex mutex;
00363 #endif
00364
00365 public:
00369 ThreadLock();
00370
00374 virtual ~ThreadLock();
00375
00379 void readLock(void);
00380
00384 void writeLock(void);
00385
00391 bool tryReadLock(void);
00392
00398 bool tryWriteLock(void);
00399
00403 void unlock(void);
00404 };
00405
00426 class __EXPORT ReadLock
00427 {
00428 private:
00429 ThreadLock& tl;
00430
00431 public:
00437 ReadLock( ThreadLock& _tl ) : tl( _tl )
00438 { tl.readLock(); }
00442
00443 ~ReadLock()
00444 { tl.unlock(); }
00445 };
00446
00467 class __EXPORT WriteLock
00468 {
00469 private:
00470 ThreadLock& tl;
00471
00472 public:
00478 WriteLock( ThreadLock& _tl ) : tl( _tl )
00479 { tl.writeLock(); }
00483
00484 ~WriteLock()
00485 { tl.unlock(); }
00486 };
00487
00488
00498 class __EXPORT MutexCounter : public Mutex
00499 {
00500 private:
00501 volatile int counter;
00502
00503 public:
00509 MutexCounter(const char *id = NULL);
00510
00518 MutexCounter(int initial, const char *id = NULL);
00519
00520 friend __EXPORT int operator++(MutexCounter &mc);
00521 friend __EXPORT int operator--(MutexCounter &mc);
00522 };
00523
00534 class __EXPORT AtomicCounter
00535 {
00536 #ifndef CCXX_USE_WIN32_ATOMIC
00537 private:
00538 #if defined(HAVE_ATOMIC_AIX)
00539 volatile int counter;
00540 #elif defined(HAVE_GCC_BITS_ATOMIC)
00541 volatile _Atomic_word counter;
00542 #elif defined(HAVE_GCC_CXX_BITS_ATOMIC)
00543 volatile _Atomic_word counter;
00544
00545 #elif defined(HAVE_ATOMIC)
00546 atomic_t atomic;
00547 #else
00548 volatile int counter;
00549 pthread_mutex_t _mutex;
00550 #endif
00551
00552 public:
00556 AtomicCounter();
00557
00563 AtomicCounter(int value);
00564
00565 ~AtomicCounter();
00566
00567 int operator++(void);
00568 int operator--(void);
00569 int operator+=(int change);
00570 int operator-=(int change);
00571 int operator+(int change);
00572 int operator-(int change);
00573 int operator=(int value);
00574 bool operator!(void);
00575 operator int();
00576 #else
00577 private:
00578 long atomic;
00579
00580 public:
00581 inline AtomicCounter()
00582 {atomic = 0;};
00583
00584 inline AtomicCounter(int value)
00585 {atomic = value;};
00586
00587 inline int operator++(void)
00588 {return InterlockedIncrement(&atomic);};
00589
00590 inline int operator--(void)
00591 {return InterlockedDecrement(&atomic);};
00592
00593 int operator+=(int change);
00594
00595 int operator-=(int change);
00596
00597 inline int operator+(int change)
00598 {return atomic + change;};
00599
00600 inline int operator-(int change)
00601 {return atomic - change;};
00602
00603 inline int operator=(int value)
00604 {return InterlockedExchange(&atomic, value);};
00605
00606 inline bool operator!(void)
00607 {return (atomic == 0) ? true : false;};
00608
00609 inline operator int()
00610 {return atomic;};
00611 #endif
00612 };
00613
00614 #ifndef WIN32
00615
00635 class __EXPORT Conditional
00636 {
00637 private:
00638 pthread_cond_t _cond;
00639 pthread_mutex_t _mutex;
00640
00641 public:
00647 Conditional(const char *id = NULL);
00648
00652 virtual ~Conditional();
00653
00659 void signal(bool broadcast);
00660
00667 bool wait(timeout_t timer = 0, bool locked = false);
00668
00675 void enterMutex(void);
00676
00685 inline void lock(void)
00686 {enterMutex();};
00687
00698 bool tryEnterMutex(void);
00699
00700 inline bool test(void)
00701 {return tryEnterMutex();};
00702
00708 void leaveMutex(void);
00709
00710 inline void unlock(void)
00711 {return leaveMutex();};
00712 };
00713 #endif
00714
00732 class __EXPORT Semaphore
00733 {
00734 private:
00735 #ifndef WIN32
00736 unsigned _count, _waiters;
00737 pthread_mutex_t _mutex;
00738 pthread_cond_t _cond;
00739 #else
00740 HANDLE semObject;
00741 #endif // !WIN32
00742
00743 public:
00752 Semaphore(unsigned resource = 0);
00753
00760 virtual ~Semaphore();
00761
00777 bool wait(timeout_t timeout = 0);
00778
00790 void post(void);
00791
00792
00793
00794
00795 #if 0
00796
00801 int getValue(void);
00802 #endif
00803 };
00804
00824 class __EXPORT SemaphoreLock
00825 {
00826 private:
00827 Semaphore& sem;
00828
00829 public:
00833 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00834 { sem.wait(); }
00838
00839 ~SemaphoreLock()
00840 { sem.post(); }
00841 };
00842
00856 class __EXPORT Event
00857 {
00858 private:
00859 #ifndef WIN32
00860 pthread_mutex_t _mutex;
00861 pthread_cond_t _cond;
00862 bool _signaled;
00863 int _count;
00864 #else
00865 HANDLE cond;
00866 #endif
00867
00868 public:
00869 Event();
00870
00871 virtual ~Event();
00872
00879 void reset(void);
00880
00884 void signal(void);
00885
00894 bool wait(timeout_t timer);
00895 bool wait(void);
00896 };
00897
00898
01080 class __EXPORT Thread
01081 {
01082 public:
01086 typedef enum Throw {
01087 throwNothing,
01088 throwObject,
01089 throwException
01090 } Throw;
01091
01095 typedef enum Cancel {
01096 cancelInitial=0,
01097 cancelDeferred=1,
01098 cancelImmediate,
01099 cancelDisabled,
01100 cancelManual,
01102 cancelDefault=cancelDeferred
01104 } Cancel;
01105
01109 typedef enum Suspend {
01110 suspendEnable,
01111 suspendDisable
01112 } Suspend;
01113
01114 #ifndef WIN32
01115
01116 friend class PosixThread;
01117 #endif
01118
01119 friend class DummyThread;
01120 private:
01121 friend class Cancellation;
01122 friend class postream_type;
01123 friend class Slog;
01124
01125 Semaphore joinSem;
01126 static Thread* _main;
01127
01128 Thread *_parent;
01129 Cancel _cancel;
01130 Semaphore *_start;
01131
01132
01133 friend class ThreadImpl;
01134 class ThreadImpl* priv;
01135
01136 public:
01137 static Thread *get(void);
01138
01139 private:
01140 #ifdef WIN32
01141 static unsigned __stdcall Execute(Thread *th);
01142 #endif
01143
01144
01145 void close();
01146
01147 private:
01148 char _name[32];
01149 static size_t _autostack;
01150
01151 #ifdef WIN32
01152 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01153 #endif
01154
01155 protected:
01163 void setName(const char *text);
01164
01174 virtual void run(void) = 0;
01175
01197 virtual void final(void);
01198
01210 virtual void initial(void);
01211
01221 virtual void* getExtended(void);
01222
01230 virtual void notify(Thread*);
01231
01237 void exit(void);
01238
01242 void sync(void);
01243
01247 bool testCancel(void);
01248
01258 void setCancel(Cancel mode);
01259
01267 void setSuspend(Suspend mode);
01268
01277 void terminate(void);
01278
01282 inline void clrParent(void)
01283 {_parent = NULL;};
01284
01285 public:
01294 Thread(bool isMain);
01295
01307 Thread(int pri = 0, size_t stack = 0);
01308
01309 #ifndef WIN32
01310
01318 Thread(const Thread &th);
01319 #endif
01320
01327 virtual ~Thread();
01328
01334 static void setStack(size_t size = 0)
01335 {_autostack = size;};
01336
01346 static void sleep(timeout_t msec);
01347
01352 static void yield(void);
01353
01366 int start(Semaphore *start = 0);
01367
01376 int detach(Semaphore *start = 0);
01377
01384 inline Thread *getParent(void)
01385 {return _parent;};
01386
01393 void suspend(void);
01394
01398 void resume(void);
01399
01406 inline Cancel getCancel(void)
01407 {return _cancel;};
01408
01415 bool isRunning(void) const;
01416
01422 bool isDetached(void) const;
01423
01427 void join(void);
01428
01435 bool isThread(void) const;
01436
01442 cctid_t getId(void) const;
01443
01450 const char *getName(void) const
01451 {return _name;};
01452
01458 static Throw getException(void);
01459
01465 static void setException(Throw mode);
01466
01473 friend inline void operator++(Thread &th)
01474 {if (th._start) th._start->post();};
01475
01476 friend inline void operator--(Thread &th)
01477 {if (th._start) th._start->wait();};
01478
01479 #ifdef WIN32
01480 bool isCancelled() const;
01481
01482 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01483 #endif
01484
01492 static Cancel enterCancel(void);
01493
01499 static void exitCancel(Cancel cancel);
01500 };
01501
01511 class __EXPORT Cancellation
01512 {
01513 private:
01514 Thread::Cancel prior;
01515
01516 public:
01517 Cancellation(Thread::Cancel cancel);
01518 ~Cancellation();
01519 };
01520
01521 #if !defined(WIN32) && !defined(__MINGW32__)
01522 typedef int signo_t;
01523
01524 class PosixThread: public Thread
01525 {
01526 private:
01527 #ifndef WIN32
01528
01529 friend class ThreadImpl;
01530 friend class Thread;
01531 #endif
01532 #ifndef CCXX_SIG_THREAD_ALARM
01533 static PosixThread *_timer;
01534 static Mutex _arm;
01535 #endif
01536
01537 time_t _alarm;
01538 static void signalThread(Thread* th,signo_t signo);
01539 protected:
01540
01547 inline void signalParent(signo_t signo)
01548 { signalThread(_parent,signo); };
01549
01556 inline void signalMain(signo_t signo)
01557 { signalThread(_main,signo);};
01558
01563 virtual void onTimer(void);
01564
01569 virtual void onHangup(void);
01570
01575 virtual void onException(void);
01576
01581 virtual void onDisconnect(void);
01582
01587 virtual void onPolling(void);
01588
01595 virtual void onSignal(int);
01596
01609 void setTimer(timeout_t timer, bool periodic = false);
01610
01617 timeout_t getTimer(void) const;
01618
01624 void endTimer(void);
01625
01626 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01627
01633 void waitSignal(signo_t signo);
01634 #endif
01635
01642 void setSignal(int signo, bool active);
01643
01650 pthread_attr_t *getPthreadAttrPtr(void);
01651
01656 pthread_t getPthreadId(void);
01657
01658 public:
01659
01660 PosixThread(int pri = 0, size_t stack = 0);
01661
01667 inline void signalThread(int signo)
01668 {signalThread(this, signo);};
01669
01676 static void sigInstall(int signo);
01677 };
01678 #endif
01679
01694 class __EXPORT ThreadKey
01695 {
01696 private:
01697 #ifndef WIN32
01698 pthread_key_t key;
01699 typedef void (*TDestruct)(void*);
01700 friend class ThreadImpl;
01701 ThreadKey(TDestruct destruct);
01702 #else
01703 DWORD key;
01704 #endif
01705
01706 public:
01710 ThreadKey();
01711
01715 virtual ~ThreadKey();
01716
01724 void *getKey(void);
01725
01733 void setKey(void *);
01734 };
01735
01746 class __EXPORT TimerPort
01747 {
01748 #ifndef WIN32
01749 struct timeval timer;
01750 #else
01751 DWORD timer;
01752 #endif
01753 bool active;
01754
01755 public:
01762 TimerPort();
01763
01772 void setTimer(timeout_t timeout = 0);
01773
01783 void incTimer(timeout_t timeout);
01784
01794 void decTimer(timeout_t timeout);
01795
01800 void sleepTimer(void);
01801
01807 void endTimer(void);
01808
01820 timeout_t getTimer(void) const;
01821
01831 timeout_t getElapsed(void) const;
01832 };
01833
01834
01835
01836
01837 #if !defined(WIN32)
01838
01839
01840 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01841
01842 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01843 void wait(signo_t signo);
01844 #endif
01845
01846 #endif // !WIN32
01847
01848 #ifdef USE_POLL
01849
01857 class Poller
01858 {
01859 private:
01860 int nufds;
01861 pollfd *ufds;
01862
01863 public:
01864 Poller();
01865
01866 virtual ~Poller();
01867
01875 pollfd *getList(int cnt);
01876
01882 inline pollfd *getList(void)
01883 {return ufds;};
01884 };
01885 #endif
01886
01887 inline Thread *getThread(void)
01888 {return Thread::get();}
01889
01919 class __EXPORT SysTime
01920 {
01921 private:
01922 static Mutex timeLock;
01923
01924 protected:
01925 inline static void lock(void)
01926 {timeLock.enterMutex();}
01927
01928 inline static void unlock(void)
01929 {timeLock.leaveMutex();}
01930
01931 public:
01932 static time_t getTime(time_t *tloc = NULL);
01933 static time_t time(time_t *tloc)
01934 { return getTime(tloc); };
01935
01936 static int getTimeOfDay(struct timeval *tp);
01937 static int gettimeofday(struct timeval *tp, struct timezone *)
01938 { return getTimeOfDay(tp); };
01939
01940 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01941 static struct tm *locatime(const time_t *clock, struct tm *result)
01942 { return getLocalTime(clock, result); };
01943
01944 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01945 static struct tm *gmtime(const time_t *clock, struct tm *result)
01946 { return getGMTTime(clock, result);};
01947 };
01948
01949 #ifndef HAVE_LOCALTIME_R
01950
01951 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01952 {return SysTime::getLocalTime(t, b);};
01953 inline char *ctime_r(const time_t *t, char *buf)
01954 {return ctime(t);};
01955 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01956 {return SysTime::getGMTTime(t, b);};
01957 inline char *asctime_r(const struct tm *tm, char *b) \
01958 {return asctime(tm);};
01959
01960 #endif
01961
01962 #ifdef CCXX_NAMESPACES
01963 }
01964 #endif
01965
01966 #endif
01967