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:
00219 Mutex(const char *name = NULL);
00220
00226 virtual ~Mutex();
00227
00233 static void setDebug(bool mode)
00234 {_debug = mode;};
00235
00241 inline void nameMutex(const char *cp)
00242 {_name = cp;};
00243
00251 void enterMutex(void);
00252
00256 inline void enter(void)
00257 {enterMutex();};
00258
00259 inline void leave(void)
00260 {leaveMutex();};
00261
00262 inline bool test(void)
00263 {return tryEnterMutex();};
00264
00275 bool tryEnterMutex(void);
00276
00287 void leaveMutex(void);
00288 };
00289
00313 class __EXPORT MutexLock
00314 {
00315 private:
00316 Mutex& mutex;
00317 public:
00321 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00322 { mutex.enterMutex(); }
00326
00327 ~MutexLock()
00328 { mutex.leaveMutex(); }
00329 };
00330
00339 class __EXPORT ThreadLock
00340 {
00341 private:
00342 #ifdef HAVE_PTHREAD_RWLOCK
00343 pthread_rwlock_t _lock;
00344 #else
00345 Mutex mutex;
00346 #endif
00347
00348 public:
00352 ThreadLock();
00353
00357 virtual ~ThreadLock();
00358
00362 void readLock(void);
00363
00367 void writeLock(void);
00368
00374 bool tryReadLock(void);
00375
00381 bool tryWriteLock(void);
00382
00386 void unlock(void);
00387 };
00388
00409 class __EXPORT ReadLock
00410 {
00411 private:
00412 ThreadLock& tl;
00413
00414 public:
00418 ReadLock( ThreadLock& _tl ) : tl( _tl )
00419 { tl.readLock(); }
00423
00424 ~ReadLock()
00425 { tl.unlock(); }
00426 };
00427
00448 class __EXPORT WriteLock
00449 {
00450 private:
00451 ThreadLock& tl;
00452
00453 public:
00457 WriteLock( ThreadLock& _tl ) : tl( _tl )
00458 { tl.writeLock(); }
00462
00463 ~WriteLock()
00464 { tl.unlock(); }
00465 };
00466
00467
00477 class __EXPORT MutexCounter : public Mutex
00478 {
00479 private:
00480 volatile int counter;
00481
00482 public:
00483 MutexCounter(const char *id = NULL);
00484 MutexCounter(int initial, const char *id = NULL);
00485
00486 friend __EXPORT int operator++(MutexCounter &mc);
00487 friend __EXPORT int operator--(MutexCounter &mc);
00488 };
00489
00500 class __EXPORT AtomicCounter
00501 {
00502 #ifndef CCXX_USE_WIN32_ATOMIC
00503 private:
00504 #if defined(HAVE_ATOMIC_AIX)
00505 volatile int counter;
00506 #elif defined(HAVE_GCC_BITS_ATOMIC)
00507 volatile _Atomic_word counter;
00508 #elif defined(HAVE_GCC_CXX_BITS_ATOMIC)
00509 volatile _Atomic_word counter;
00510
00511 #elif defined(HAVE_ATOMIC)
00512 atomic_t atomic;
00513 #else
00514 volatile int counter;
00515 pthread_mutex_t _mutex;
00516 #endif
00517
00518 public:
00522 AtomicCounter();
00523
00529 AtomicCounter(int value);
00530
00531 ~AtomicCounter();
00532
00533 int operator++(void);
00534 int operator--(void);
00535 int operator+=(int change);
00536 int operator-=(int change);
00537 int operator+(int change);
00538 int operator-(int change);
00539 int operator=(int value);
00540 bool operator!(void);
00541 operator int();
00542 #else
00543 private:
00544 long atomic;
00545
00546 public:
00547 inline AtomicCounter()
00548 {atomic = 0;};
00549
00550 inline AtomicCounter(int value)
00551 {atomic = value;};
00552
00553 inline int operator++(void)
00554 {return InterlockedIncrement(&atomic);};
00555
00556 inline int operator--(void)
00557 {return InterlockedDecrement(&atomic);};
00558
00559 int operator+=(int change);
00560
00561 int operator-=(int change);
00562
00563 inline int operator+(int change)
00564 {return atomic + change;};
00565
00566 inline int operator-(int change)
00567 {return atomic - change;};
00568
00569 inline int operator=(int value)
00570 {return InterlockedExchange(&atomic, value);};
00571
00572 inline bool operator!(void)
00573 {return (atomic == 0) ? true : false;};
00574
00575 inline operator int()
00576 {return atomic;};
00577 #endif
00578 };
00579
00580 #ifndef WIN32
00581
00601 class __EXPORT Conditional
00602 {
00603 private:
00604 pthread_cond_t _cond;
00605 pthread_mutex_t _mutex;
00606
00607 public:
00611 Conditional(const char *id = NULL);
00612
00616 virtual ~Conditional();
00617
00623 void signal(bool broadcast);
00624
00631 bool wait(timeout_t timer = 0, bool locked = false);
00632
00639 void enterMutex(void);
00640
00649 inline void lock(void)
00650 {enterMutex();};
00651
00662 bool tryEnterMutex(void);
00663
00664 inline bool test(void)
00665 {return tryEnterMutex();};
00666
00672 void leaveMutex(void);
00673
00674 inline void unlock(void)
00675 {return leaveMutex();};
00676 };
00677 #endif
00678
00696 class __EXPORT Semaphore
00697 {
00698 private:
00699 #ifndef WIN32
00700 unsigned _count, _waiters;
00701 pthread_mutex_t _mutex;
00702 pthread_cond_t _cond;
00703 #else
00704 HANDLE semObject;
00705 #endif // !WIN32
00706
00707 public:
00716 Semaphore(unsigned resource = 0);
00717
00724 virtual ~Semaphore();
00725
00741 bool wait(timeout_t timeout = 0);
00742
00754 void post(void);
00755
00756
00757
00758
00759 #if 0
00760
00765 int getValue(void);
00766 #endif
00767 };
00768
00788 class __EXPORT SemaphoreLock
00789 {
00790 private:
00791 Semaphore& sem;
00792
00793 public:
00797 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00798 { sem.wait(); }
00802
00803 ~SemaphoreLock()
00804 { sem.post(); }
00805 };
00806
00820 class __EXPORT Event
00821 {
00822 private:
00823 #ifndef WIN32
00824 pthread_mutex_t _mutex;
00825 pthread_cond_t _cond;
00826 bool _signaled;
00827 int _count;
00828 #else
00829 HANDLE cond;
00830 #endif
00831
00832 public:
00833 Event();
00834
00835 virtual ~Event();
00836
00843 void reset(void);
00844
00848 void signal(void);
00849
00858 bool wait(timeout_t timer);
00859 bool wait(void);
00860 };
00861
00862
01044 class __EXPORT Thread
01045 {
01046 public:
01050 typedef enum Throw {
01051 throwNothing,
01052 throwObject,
01053 throwException
01054 } Throw;
01055
01059 typedef enum Cancel
01060 {
01061 cancelInitial=0,
01062 cancelDeferred=1,
01063 cancelImmediate,
01064 cancelDisabled,
01065 cancelManual,
01067 cancelDefault=cancelDeferred
01069 } Cancel;
01070
01074 typedef enum Suspend
01075 {
01076 suspendEnable,
01077 suspendDisable
01078 } Suspend;
01079
01080 #ifndef WIN32
01081
01082 friend class PosixThread;
01083 #endif
01084
01085 friend class DummyThread;
01086 private:
01087 friend class Cancellation;
01088 friend class postream_type;
01089 friend class Slog;
01090
01091 Semaphore joinSem;
01092 static Thread* _main;
01093
01094 Thread *_parent;
01095 Cancel _cancel;
01096 Semaphore *_start;
01097
01098
01099 friend class ThreadImpl;
01100 class ThreadImpl* priv;
01101
01102 public:
01103 static Thread *get(void);
01104
01105 private:
01106 #ifdef WIN32
01107 static unsigned __stdcall Execute(Thread *th);
01108 #endif
01109
01110
01111 void close();
01112
01113 private:
01114 char _name[32];
01115 static size_t _autostack;
01116
01117 #ifdef WIN32
01118 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01119 #endif
01120
01121 protected:
01129 void setName(const char *text);
01130
01140 virtual void run(void) = 0;
01141
01163 virtual void final(void);
01164
01176 virtual void initial(void);
01177
01187 virtual void* getExtended(void);
01188
01196 virtual void notify(Thread*);
01197
01203 void exit(void);
01204
01208 void sync(void);
01209
01213 bool testCancel(void);
01214
01224 void setCancel(Cancel mode);
01225
01233 void setSuspend(Suspend mode);
01234
01243 void terminate(void);
01244
01248 inline void clrParent(void)
01249 {_parent = NULL;};
01250
01251 public:
01260 Thread(bool isMain);
01261
01273 Thread(int pri = 0, size_t stack = 0);
01274
01275 #ifndef WIN32
01276
01284 Thread(const Thread &th);
01285 #endif
01286
01293 virtual ~Thread();
01294
01300 static void setStack(size_t size = 0)
01301 {_autostack = size;};
01302
01312 static void sleep(timeout_t msec);
01313
01318 static void yield(void);
01319
01332 int start(Semaphore *start = 0);
01333
01342 int detach(Semaphore *start = 0);
01343
01350 inline Thread *getParent(void)
01351 {return _parent;};
01352
01359 void suspend(void);
01360
01364 void resume(void);
01365
01372 inline Cancel getCancel(void)
01373 {return _cancel;};
01374
01381 bool isRunning(void);
01382
01388 bool isDetached(void);
01389
01393 void join(void);
01394
01401 bool isThread(void);
01402
01408 cctid_t getId(void) const;
01409
01416 const char *getName(void)
01417 {return _name;};
01418
01424 static Throw getException(void);
01425
01431 static void setException(Throw mode);
01432
01439 friend inline void operator++(Thread &th)
01440 {if (th._start) th._start->post();};
01441
01442 friend inline void operator--(Thread &th)
01443 {if (th._start) th._start->wait();};
01444
01445 #ifdef WIN32
01446 bool isCancelled();
01447
01448 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01449 #endif
01450
01458 static Cancel enterCancel(void);
01459
01465 static void exitCancel(Cancel cancel);
01466 };
01467
01477 class __EXPORT Cancellation
01478 {
01479 private:
01480 Thread::Cancel prior;
01481
01482 public:
01483 Cancellation(Thread::Cancel cancel);
01484 ~Cancellation();
01485 };
01486
01487 #if !defined(WIN32) && !defined(__MINGW32__)
01488 typedef int signo_t;
01489
01490 class PosixThread: public Thread
01491 {
01492 private:
01493 #ifndef WIN32
01494
01495 friend class ThreadImpl;
01496 friend class Thread;
01497 #endif
01498 #ifndef CCXX_SIG_THREAD_ALARM
01499 static PosixThread *_timer;
01500 static Mutex _arm;
01501 #endif
01502
01503 time_t _alarm;
01504 static void signalThread(Thread* th,signo_t signo);
01505 protected:
01506
01513 inline void signalParent(signo_t signo)
01514 { signalThread(_parent,signo); };
01515
01522 inline void signalMain(signo_t signo)
01523 { signalThread(_main,signo);};
01524
01529 virtual void onTimer(void);
01530
01535 virtual void onHangup(void);
01536
01541 virtual void onException(void);
01542
01547 virtual void onDisconnect(void);
01548
01553 virtual void onPolling(void);
01554
01561 virtual void onSignal(int);
01562
01575 void setTimer(timeout_t timer, bool periodic = false);
01576
01583 timeout_t getTimer(void) const;
01584
01590 void endTimer(void);
01591
01592 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01593
01599 void waitSignal(signo_t signo);
01600 #endif
01601
01608 void setSignal(int signo, bool active);
01609
01616 pthread_attr_t *getPthreadAttrPtr(void);
01617
01622 pthread_t getPthreadId(void);
01623
01624 public:
01625
01626 PosixThread(int pri = 0, size_t stack = 0);
01627
01633 inline void signalThread(int signo)
01634 {signalThread(this, signo);};
01635
01642 static void sigInstall(int signo);
01643 };
01644 #endif
01645
01660 class __EXPORT ThreadKey
01661 {
01662 private:
01663 #ifndef WIN32
01664 pthread_key_t key;
01665 typedef void (*TDestruct)(void*);
01666 friend class ThreadImpl;
01667 ThreadKey(TDestruct destruct);
01668 #else
01669 DWORD key;
01670 #endif
01671
01672 public:
01676 ThreadKey();
01677
01681 virtual ~ThreadKey();
01682
01690 void *getKey(void);
01691
01699 void setKey(void *);
01700 };
01701
01712 class __EXPORT TimerPort
01713 {
01714 #ifndef WIN32
01715 struct timeval timer;
01716 #else
01717 DWORD timer;
01718 #endif
01719 bool active;
01720
01721 public:
01728 TimerPort();
01729
01738 void setTimer(timeout_t timeout = 0);
01739
01749 void incTimer(timeout_t timeout);
01750
01756 void endTimer(void);
01757
01769 timeout_t getTimer(void) const;
01770
01780 timeout_t getElapsed(void) const;
01781 };
01782
01783
01784
01785
01786 #if !defined(WIN32)
01787
01788
01789 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01790
01791 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01792 void wait(signo_t signo);
01793 #endif
01794
01795 #endif // !WIN32
01796
01797 #ifdef USE_POLL
01798
01806 class Poller
01807 {
01808 private:
01809 int nufds;
01810 pollfd *ufds;
01811
01812 public:
01813 Poller();
01814
01815 virtual ~Poller();
01816
01824 pollfd *getList(int cnt);
01825
01831 inline pollfd *getList(void)
01832 {return ufds;};
01833 };
01834 #endif
01835
01836 inline Thread *getThread(void)
01837 {return Thread::get();}
01838
01868 class __EXPORT SysTime
01869 {
01870 private:
01871 static Mutex timeLock;
01872
01873 protected:
01874 inline static void lock(void)
01875 {timeLock.enterMutex();}
01876
01877 inline static void unlock(void)
01878 {timeLock.leaveMutex();}
01879
01880 public:
01881 static time_t getTime(time_t *tloc = NULL);
01882 static time_t time(time_t *tloc)
01883 { return getTime(tloc); };
01884
01885 static int getTimeOfDay(struct timeval *tp);
01886 static int gettimeofday(struct timeval *tp, struct timezone *)
01887 { return getTimeOfDay(tp); };
01888
01889 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01890 static struct tm *locatime(const time_t *clock, struct tm *result)
01891 { return getLocalTime(clock, result); };
01892
01893 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01894 static struct tm *gmtime(const time_t *clock, struct tm *result)
01895 { return getGMTTime(clock, result);};
01896 };
01897
01898 #ifndef HAVE_LOCALTIME_R
01899
01900 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01901 {return SysTime::getLocalTime(t, b);};
01902 inline char *ctime_r(const time_t *t, char *buf)
01903 {return ctime(t);};
01904 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01905 {return SysTime::getGMTTime(t, b);};
01906 inline char *asctime_r(const struct tm *tm, char *b) \
01907 {return asctime(tm);};
01908
01909 #endif
01910
01911 #ifdef CCXX_NAMESPACES
01912 }
01913 #endif
01914
01915 #endif
01916