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 #ifndef WIN32
00047 #define CCXX_POSIX
00048 #endif // !WIN32
00049
00050 #ifndef CCXX_CONFIG_H_
00051 #include <cc++/config.h>
00052 #endif
00053
00054 #include <ctime>
00055
00056 #ifndef WIN32
00057 #include <pthread.h>
00058 #endif // !WIN32
00059
00060 #undef CCXX_USE_WIN32_ATOMIC
00061 #ifndef WIN32
00062 #include <time.h>
00063 #include <signal.h>
00064 #include <unistd.h>
00065
00066 #ifdef _THR_UNIXWARE
00067 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00068 #endif
00069
00070 typedef pthread_t cctid_t;
00071 typedef unsigned long timeout_t;
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #else // WIN32
00083 typedef DWORD cctid_t;
00084 typedef DWORD timeout_t;
00085
00086 #define MAX_SEM_VALUE 1000000
00087 #define CCXX_USE_WIN32_ATOMIC 1
00088
00089 #endif // !WIN32
00090
00091 #ifdef CCXX_NAMESPACES
00092 namespace ost {
00093 #endif
00094
00095 class __EXPORT Thread;
00096 class __EXPORT ThreadKey;
00097
00098 #define TIMEOUT_INF ~((timeout_t) 0)
00099
00100 #define ENTER_CRITICAL enterMutex();
00101 #define LEAVE_CRITICAL leaveMutex();
00102 #define ENTER_DEFERRED setCancel(cancelDeferred);
00103 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00104
00105 #ifndef WIN32
00106
00107
00108
00109
00110
00111
00112 #undef sleep
00113 #define psleep(x) (sleep)(x)
00114
00115 #ifdef signal
00116 #undef signal
00117 #endif
00118
00119 #endif // !WIN32
00120
00121 #undef Yield
00122
00123 class __EXPORT Conditional;
00124 class __EXPORT Event;
00125
00169 class __EXPORT Mutex
00170 {
00171 private:
00172 static bool _debug;
00173 const char *_name;
00174 #ifndef WIN32
00175 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00176 int volatile _level;
00177 Thread *volatile _tid;
00178 #endif
00179
00180
00181
00182
00183
00184
00185
00186
00187 pthread_mutex_t _mutex;
00188 #else // WIN32
00189
00190 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00191 # error "Can't determine underground for Mutex"
00192 # endif
00193
00194 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00195 HANDLE _mutex;
00196 #endif
00197 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00198 CRITICAL_SECTION _criticalSection;
00199 #endif
00200
00201 #endif // WIN32
00202
00203 public:
00207 Mutex(const char *name = NULL);
00208
00214 virtual ~Mutex();
00215
00221 static void setDebug(bool mode)
00222 {_debug = mode;};
00223
00231 void enterMutex(void);
00232
00236 inline void enter(void)
00237 {enterMutex();};
00238
00239 inline void leave(void)
00240 {leaveMutex();};
00241
00242 inline bool test(void)
00243 {return tryEnterMutex();};
00244
00255 bool tryEnterMutex(void);
00256
00267 void leaveMutex(void);
00268 };
00269
00293 class __EXPORT MutexLock
00294 {
00295 private:
00296 Mutex& mutex;
00297 public:
00301 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00302 { mutex.enterMutex(); }
00306
00307 ~MutexLock()
00308 { mutex.leaveMutex(); }
00309 };
00310
00319 class __EXPORT ThreadLock
00320 {
00321 private:
00322 #ifdef HAVE_PTHREAD_RWLOCK
00323 pthread_rwlock_t _lock;
00324 #else
00325 Mutex mutex;
00326 #endif
00327
00328 public:
00332 ThreadLock();
00333
00337 virtual ~ThreadLock();
00338
00342 void readLock(void);
00343
00347 void writeLock(void);
00348
00354 bool tryReadLock(void);
00355
00361 bool tryWriteLock(void);
00362
00366 void unlock(void);
00367 };
00368
00389 class __EXPORT ReadLock
00390 {
00391 private:
00392 ThreadLock& tl;
00393
00394 public:
00398 ReadLock( ThreadLock& _tl ) : tl( _tl )
00399 { tl.readLock(); }
00403
00404 ~ReadLock()
00405 { tl.unlock(); }
00406 };
00407
00428 class __EXPORT WriteLock
00429 {
00430 private:
00431 ThreadLock& tl;
00432
00433 public:
00437 WriteLock( ThreadLock& _tl ) : tl( _tl )
00438 { tl.writeLock(); }
00442
00443 ~WriteLock()
00444 { tl.unlock(); }
00445 };
00446
00447
00457 class __EXPORT MutexCounter : public Mutex
00458 {
00459 private:
00460 volatile int counter;
00461
00462 public:
00463 MutexCounter(const char *id = NULL);
00464 MutexCounter(int initial, const char *id = NULL);
00465
00466 friend __EXPORT int operator++(MutexCounter &mc);
00467 friend __EXPORT int operator--(MutexCounter &mc);
00468 };
00469
00480 class __EXPORT AtomicCounter
00481 {
00482 #ifndef CCXX_USE_WIN32_ATOMIC
00483 private:
00484 #ifdef HAVE_ATOMIC_AIX
00485 volatile int counter;
00486 #elif HAVE_ATOMIC
00487 atomic_t atomic;
00488 #else
00489 volatile int counter;
00490 pthread_mutex_t _mutex;
00491 #endif
00492
00493 public:
00497 AtomicCounter();
00498
00504 AtomicCounter(int value);
00505
00506 ~AtomicCounter();
00507
00508 int operator++(void);
00509 int operator--(void);
00510 int operator+=(int change);
00511 int operator-=(int change);
00512 int operator+(int change);
00513 int operator-(int change);
00514 int operator=(int value);
00515 bool operator!(void);
00516 operator int();
00517 #else
00518 private:
00519 long atomic;
00520
00521 public:
00522 inline AtomicCounter()
00523 {atomic = 0;};
00524
00525 inline AtomicCounter(int value)
00526 {atomic = value;};
00527
00528 inline int operator++(void)
00529 {return InterlockedIncrement(&atomic);};
00530
00531 inline int operator--(void)
00532 {return InterlockedDecrement(&atomic);};
00533
00534 int operator+=(int change);
00535
00536 int operator-=(int change);
00537
00538 inline int operator+(int change)
00539 {return atomic + change;};
00540
00541 inline int operator-(int change)
00542 {return atomic - change;};
00543
00544 inline int operator=(int value)
00545 {return InterlockedExchange(&atomic, value);};
00546
00547 inline bool operator!(void)
00548 {return (atomic == 0) ? true : false;};
00549
00550 inline operator int()
00551 {return atomic;};
00552 #endif
00553 };
00554
00555 #ifndef WIN32
00556
00576 class __EXPORT Conditional
00577 {
00578 private:
00579 pthread_cond_t _cond;
00580 pthread_mutex_t _mutex;
00581
00582 public:
00586 Conditional(const char *id = NULL);
00587
00591 virtual ~Conditional();
00592
00598 void signal(bool broadcast);
00599
00606 bool wait(timeout_t timer = 0, bool locked = false);
00607
00614 void enterMutex(void);
00615
00624 inline void lock(void)
00625 {enterMutex();};
00626
00637 bool tryEnterMutex(void);
00638
00639 inline bool test(void)
00640 {return tryEnterMutex();};
00641
00647 void leaveMutex(void);
00648
00649 inline void unlock(void)
00650 {return leaveMutex();};
00651 };
00652 #endif
00653
00671 class __EXPORT Semaphore
00672 {
00673 private:
00674 #ifndef WIN32
00675 unsigned _count, _waiters;
00676 pthread_mutex_t _mutex;
00677 pthread_cond_t _cond;
00678 #else
00679 HANDLE semObject;
00680 #endif // !WIN32
00681
00682 public:
00691 Semaphore(unsigned resource = 0);
00692
00699 virtual ~Semaphore();
00700
00716 bool wait(timeout_t timeout = 0);
00717
00729 void post(void);
00730
00731
00737 #ifndef WIN32
00738 #ifndef __CYGWIN32__
00739 int getValue(void);
00740 #endif
00741 #endif
00742 };
00743
00763 class __EXPORT SemaphoreLock
00764 {
00765 private:
00766 Semaphore& sem;
00767
00768 public:
00772 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00773 { sem.wait(); }
00777
00778 ~SemaphoreLock()
00779 { sem.post(); }
00780 };
00781
00795 class __EXPORT Event
00796 {
00797 private:
00798 #ifndef WIN32
00799 pthread_mutex_t _mutex;
00800 pthread_cond_t _cond;
00801 bool _signaled;
00802 int _count;
00803 #else
00804 HANDLE cond;
00805 #endif
00806
00807 public:
00808 Event();
00809
00810 virtual ~Event();
00811
00818 void reset(void);
00819
00823 void signal(void);
00824
00833 bool wait(timeout_t timer);
00834 bool wait(void);
00835 };
00836
00837
01019 class __EXPORT Thread
01020 {
01021 public:
01025 typedef enum Throw {
01026 throwNothing,
01027 throwObject,
01028 throwException
01029 } Throw;
01030
01034 typedef enum Cancel
01035 {
01036 cancelInitial=0,
01037 cancelDeferred=1,
01038 cancelImmediate,
01039 cancelDisabled,
01040 cancelManual,
01042 cancelDefault=cancelDeferred
01044 } Cancel;
01045
01049 typedef enum Suspend
01050 {
01051 suspendEnable,
01052 suspendDisable
01053 } Suspend;
01054
01055 #ifndef WIN32
01056
01057 friend class PosixThread;
01058 #endif
01059
01060 friend class DummyThread;
01061 private:
01062 friend class Cancellation;
01063 friend class postream_type;
01064 friend class Slog;
01065
01066 Semaphore joinSem;
01067 static Thread* _main;
01068
01069 Thread *_parent;
01070 Cancel _cancel;
01071 Semaphore *_start;
01072
01073
01074 friend class ThreadImpl;
01075 class ThreadImpl* priv;
01076
01077 public:
01078 static Thread *get(void);
01079
01080 private:
01081 #ifdef WIN32
01082 static unsigned __stdcall Execute(Thread *th);
01083 #endif
01084
01085
01086 void close();
01087
01088 private:
01089 char _name[32];
01090 static size_t _autostack;
01091
01092 #ifdef WIN32
01093 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01094 #endif
01095
01096 protected:
01104 void setName(const char *text);
01105
01115 virtual void run(void) = 0;
01116
01138 virtual void final(void);
01139
01151 virtual void initial(void);
01152
01162 virtual void* getExtended(void);
01163
01171 virtual void notify(Thread*);
01172
01178 void exit(void);
01179
01183 void sync(void);
01184
01188 bool testCancel(void);
01189
01199 void setCancel(Cancel mode);
01200
01208 void setSuspend(Suspend mode);
01209
01218 void terminate(void);
01219
01223 inline void clrParent(void)
01224 {_parent = NULL;};
01225
01226 public:
01235 Thread(bool isMain);
01236
01248 Thread(int pri = 0, size_t stack = 0);
01249
01250 #ifndef WIN32
01251
01259 Thread(const Thread &th);
01260 #endif
01261
01268 virtual ~Thread();
01269
01275 static void setStack(size_t size = 0)
01276 {_autostack = size;};
01277
01287 static void sleep(timeout_t msec);
01288
01293 static void yield(void);
01294
01307 int start(Semaphore *start = 0);
01308
01317 int detach(Semaphore *start = 0);
01318
01325 inline Thread *getParent(void)
01326 {return _parent;};
01327
01334 void suspend(void);
01335
01339 void resume(void);
01340
01347 inline Cancel getCancel(void)
01348 {return _cancel;};
01349
01356 bool isRunning(void);
01357
01363 bool isDetached(void);
01364
01368 void join(void);
01369
01376 bool isThread(void);
01377
01383 cctid_t getId(void) const;
01384
01391 const char *getName(void)
01392 {return _name;};
01393
01399 static Throw getException(void);
01400
01406 static void setException(Throw mode);
01407
01414 friend inline void operator++(Thread &th)
01415 {if (th._start) th._start->post();};
01416
01417 friend inline void operator--(Thread &th)
01418 {if (th._start) th._start->wait();};
01419
01420 #ifdef WIN32
01421 bool isCancelled();
01422
01423 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01424 #endif
01425
01433 static Cancel enterCancel(void);
01434
01440 static void exitCancel(Cancel cancel);
01441 };
01442
01452 class __EXPORT Cancellation
01453 {
01454 private:
01455 Thread::Cancel prior;
01456
01457 public:
01458 Cancellation(Thread::Cancel cancel);
01459 ~Cancellation();
01460 };
01461
01462 #if !defined(WIN32) && !defined(__MINGW32__)
01463 typedef int signo_t;
01464
01465 class PosixThread: public Thread
01466 {
01467 private:
01468 #ifndef WIN32
01469
01470 friend class ThreadImpl;
01471 friend class Thread;
01472 #endif
01473 #ifndef CCXX_SIG_THREAD_ALARM
01474 static PosixThread *_timer;
01475 static Mutex _arm;
01476 #endif
01477
01478 time_t _alarm;
01479 static void signalThread(Thread* th,signo_t signo);
01480 protected:
01481
01488 inline void signalParent(signo_t signo)
01489 { signalThread(_parent,signo); };
01490
01497 inline void signalMain(signo_t signo)
01498 { signalThread(_main,signo);};
01499
01504 virtual void onTimer(void);
01505
01510 virtual void onHangup(void);
01511
01516 virtual void onException(void);
01517
01522 virtual void onDisconnect(void);
01523
01528 virtual void onPolling(void);
01529
01536 virtual void onSignal(int);
01537
01550 void setTimer(timeout_t timer, bool periodic = false);
01551
01558 timeout_t getTimer(void) const;
01559
01565 void endTimer(void);
01566
01567 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01568
01574 void waitSignal(signo_t signo);
01575 #endif
01576
01583 void setSignal(int signo, bool active);
01584
01591 pthread_attr_t *getPthreadAttrPtr(void);
01592
01597 pthread_t getPthreadId(void);
01598
01599 public:
01600
01601 PosixThread(int pri = 0, size_t stack = 0);
01602
01608 inline void signalThread(int signo)
01609 {signalThread(this, signo);};
01610
01617 static void sigInstall(int signo);
01618 };
01619 #endif
01620
01635 class __EXPORT ThreadKey
01636 {
01637 private:
01638 #ifndef WIN32
01639 pthread_key_t key;
01640 typedef void (*TDestruct)(void*);
01641 friend class ThreadImpl;
01642 ThreadKey(TDestruct destruct);
01643 #else
01644 DWORD key;
01645 #endif
01646
01647 public:
01651 ThreadKey();
01652
01656 virtual ~ThreadKey();
01657
01665 void *getKey(void);
01666
01674 void setKey(void *);
01675 };
01676
01687 class __EXPORT TimerPort
01688 {
01689 #ifndef WIN32
01690 struct timeval timer;
01691 #else
01692 DWORD timer;
01693 #endif
01694 bool active;
01695
01696 public:
01703 TimerPort();
01704
01713 void setTimer(timeout_t timeout = 0);
01714
01724 void incTimer(timeout_t timeout);
01725
01731 void endTimer(void);
01732
01744 timeout_t getTimer(void) const;
01745
01755 timeout_t getElapsed(void) const;
01756 };
01757
01758
01759
01760
01761 #if !defined(WIN32)
01762
01763
01764 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01765
01766 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01767 void wait(signo_t signo);
01768 #endif
01769
01770 #endif // !WIN32
01771
01772 #ifdef USE_POLL
01773
01781 class Poller
01782 {
01783 private:
01784 int nufds;
01785 pollfd *ufds;
01786
01787 public:
01788 Poller();
01789
01790 virtual ~Poller();
01791
01799 pollfd *getList(int cnt);
01800
01806 inline pollfd *getList(void)
01807 {return ufds;};
01808 };
01809 #endif
01810
01811 inline Thread *getThread(void)
01812 {return Thread::get();}
01813
01843 class __EXPORT SysTime
01844 {
01845 private:
01846 static Mutex timeLock;
01847
01848 protected:
01849 inline static void lock(void)
01850 {timeLock.enterMutex();}
01851
01852 inline static void unlock(void)
01853 {timeLock.leaveMutex();}
01854
01855 public:
01856 static time_t getTime(time_t *tloc = NULL);
01857 static time_t time(time_t *tloc)
01858 { return getTime(tloc); };
01859
01860 static int getTimeOfDay(struct timeval *tp);
01861 static int gettimeofday(struct timeval *tp, struct timezone *)
01862 { return getTimeOfDay(tp); };
01863
01864 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01865 static struct tm *locatime(const time_t *clock, struct tm *result)
01866 { return getLocalTime(clock, result); };
01867
01868 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01869 static struct tm *gmtime(const time_t *clock, struct tm *result)
01870 { return getGMTTime(clock, result);};
01871 };
01872
01873 #ifndef HAVE_LOCALTIME_R
01874
01875 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01876 {return SysTime::getLocalTime(t, b);};
01877 inline char *ctime_r(const time_t *t, char *buf)
01878 {return ctime(t);};
01879 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01880 {return SysTime::getGMTTime(t, b);};
01881 inline char *asctime_r(const struct tm *tm, char *b) \
01882 {return asctime(tm);};
01883
01884 #endif
01885
01886 #ifdef CCXX_NAMESPACES
01887 }
01888 #endif
01889
01890 #endif
01891