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
00039
00040
00046 #ifndef CCXX_THREAD_H_
00047 #define CCXX_THREAD_H_
00048
00049 #ifndef WIN32
00050 #define CCXX_POSIX
00051 #endif // !WIN32
00052
00053 #ifndef CCXX_CONFIG_H_
00054 #include <cc++/config.h>
00055 #endif
00056
00057 #include <ctime>
00058
00059 #ifndef WIN32
00060 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00061 #define CCXX_SYSV_SEMAPHORES
00062 #endif
00063
00064 #ifdef MACOSX
00065 #define CCXX_NAMED_SEMAPHORES
00066 #define CCXX_BROKEN_SEMGETVALUE
00067 #endif
00068
00069 #ifndef HAVE_PTHREAD_H
00070 #include <pthread.h>
00071 #ifndef CCXX_SYSV_SEMAPHORES
00072 #include <semaphore.h>
00073 #endif
00074 #endif
00075 #endif // !WIN32
00076
00077 #undef CCXX_USE_WIN32_ATOMIC
00078 #ifndef WIN32
00079 #include <time.h>
00080 #include <signal.h>
00081 #include <unistd.h>
00082
00083 #ifdef _THR_UNIXWARE
00084 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00085 #endif
00086
00087 typedef pthread_t cctid_t;
00088 typedef unsigned long timeout_t;
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #else // WIN32
00100 typedef DWORD cctid_t;
00101 typedef DWORD timeout_t;
00102
00103 #define MAX_SEM_VALUE 1000000
00104 #define CCXX_USE_WIN32_ATOMIC 1
00105
00106 #endif // !WIN32
00107
00108 #ifdef CCXX_NAMESPACES
00109 namespace ost {
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 #endif // !WIN32
00133
00134 #undef Yield
00135
00136 class __EXPORT Conditional;
00137 class __EXPORT Event;
00138
00182 class __EXPORT Mutex
00183 {
00184 private:
00185 static bool _debug;
00186 const char *_name;
00187 #ifndef WIN32
00188 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00189 int volatile _level;
00190 Thread *volatile _tid;
00191 #endif
00192
00193
00194
00195
00196
00197
00198
00199
00200 pthread_mutex_t _mutex;
00201 #else // WIN32
00202
00203 # if defined(MUTEX_UNDERGROUND_WIN32_MUTEX) && defined(MUTEX_UNDERGROUND_WIN32_CRITICALSECTION)
00204 # error "Can't determine underground for Mutex"
00205 # endif
00206
00207 #ifdef MUTEX_UNDERGROUND_WIN32_MUTEX
00208 HANDLE _mutex;
00209 #endif
00210 #ifdef MUTEX_UNDERGROUND_WIN32_CRITICALSECTION
00211 CRITICAL_SECTION _criticalSection;
00212 #endif
00213
00214 #endif // WIN32
00215
00216 public:
00220 Mutex(const char *name = NULL);
00221
00227 virtual ~Mutex();
00228
00234 static void setDebug(bool mode)
00235 {_debug = mode;};
00236
00244 void enterMutex(void);
00245
00249 inline void enter(void)
00250 {enterMutex();};
00251
00252 inline void leave(void)
00253 {leaveMutex();};
00254
00255 inline bool test(void)
00256 {return tryEnterMutex();};
00257
00268 bool tryEnterMutex(void);
00269
00280 void leaveMutex(void);
00281 };
00282
00306 class __EXPORT MutexLock
00307 {
00308 private:
00309 Mutex& mutex;
00310 public:
00314 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00315 { mutex.enterMutex(); }
00319
00320 ~MutexLock()
00321 { mutex.leaveMutex(); }
00322 };
00323
00332 class __EXPORT ThreadLock
00333 {
00334 private:
00335 #ifdef HAVE_PTHREAD_RWLOCK
00336 pthread_rwlock_t _lock;
00337 #else
00338 Mutex mutex;
00339 #endif
00340
00341 public:
00345 ThreadLock();
00346
00350 virtual ~ThreadLock();
00351
00355 void readLock(void);
00356
00360 void writeLock(void);
00361
00367 bool tryReadLock(void);
00368
00374 bool tryWriteLock(void);
00375
00379 void unlock(void);
00380 };
00381
00402 class __EXPORT ReadLock
00403 {
00404 private:
00405 ThreadLock& tl;
00406
00407 public:
00411 ReadLock( ThreadLock& _tl ) : tl( _tl )
00412 { tl.readLock(); }
00416
00417 ~ReadLock()
00418 { tl.unlock(); }
00419 };
00420
00441 class __EXPORT WriteLock
00442 {
00443 private:
00444 ThreadLock& tl;
00445
00446 public:
00450 WriteLock( ThreadLock& _tl ) : tl( _tl )
00451 { tl.writeLock(); }
00455
00456 ~WriteLock()
00457 { tl.unlock(); }
00458 };
00459
00460
00470 class __EXPORT MutexCounter : public Mutex
00471 {
00472 private:
00473 volatile int counter;
00474
00475 public:
00476 MutexCounter(const char *id = NULL);
00477 MutexCounter(int initial, const char *id = NULL);
00478
00479 friend __EXPORT int operator++(MutexCounter &mc);
00480 friend __EXPORT int operator--(MutexCounter &mc);
00481 };
00482
00493 class __EXPORT AtomicCounter
00494 {
00495 #ifndef CCXX_USE_WIN32_ATOMIC
00496 private:
00497 #ifdef HAVE_ATOMIC_AIX
00498 volatile int counter;
00499 #elif HAVE_ATOMIC
00500 atomic_t atomic;
00501 #else
00502 volatile int counter;
00503 pthread_mutex_t _mutex;
00504 #endif
00505
00506 public:
00510 AtomicCounter();
00511
00517 AtomicCounter(int value);
00518
00519 ~AtomicCounter();
00520
00521 int operator++(void);
00522 int operator--(void);
00523 int operator+=(int change);
00524 int operator-=(int change);
00525 int operator+(int change);
00526 int operator-(int change);
00527 int operator=(int value);
00528 bool operator!(void);
00529 operator int();
00530 #else
00531 private:
00532 long atomic;
00533
00534 public:
00535 inline AtomicCounter()
00536 {atomic = 0;};
00537
00538 inline AtomicCounter(int value)
00539 {atomic = value;};
00540
00541 inline int operator++(void)
00542 {return InterlockedIncrement(&atomic);};
00543
00544 inline int operator--(void)
00545 {return InterlockedDecrement(&atomic);};
00546
00547 int operator+=(int change);
00548
00549 int operator-=(int change);
00550
00551 inline int operator+(int change)
00552 {return atomic + change;};
00553
00554 inline int operator-(int change)
00555 {return atomic - change;};
00556
00557 inline int operator=(int value)
00558 {return InterlockedExchange(&atomic, value);};
00559
00560 inline bool operator!(void)
00561 {return (atomic == 0) ? true : false;};
00562
00563 inline operator int()
00564 {return atomic;};
00565 #endif
00566 };
00567
00568 #ifndef WIN32
00569
00589 class __EXPORT Conditional
00590 {
00591 private:
00592 pthread_cond_t _cond;
00593 pthread_mutex_t _mutex;
00594
00595 public:
00599 Conditional(const char *id = NULL);
00600
00604 virtual ~Conditional();
00605
00611 void signal(bool broadcast);
00612
00619 bool wait(timeout_t timer = 0, bool locked = false);
00620
00627 void enterMutex(void);
00628
00637 inline void lock(void)
00638 {enterMutex();};
00639
00650 bool tryEnterMutex(void);
00651
00652 inline bool test(void)
00653 {return tryEnterMutex();};
00654
00660 void leaveMutex(void);
00661
00662 inline void unlock(void)
00663 {return leaveMutex();};
00664 };
00665 #endif
00666
00684 class __EXPORT Semaphore
00685 {
00686 private:
00687 #ifndef WIN32
00688 #ifdef CCXX_SYSV_SEMAPHORES
00689 int _semaphore;
00690 #else
00691 sem_t _semaphore;
00692 sem_t *_semobject;
00693 #endif
00694 #else // WIN32
00695 HANDLE semObject;
00696 #endif // !WIN32
00697
00698 public:
00707 Semaphore(size_t resource = 0);
00708
00715 virtual ~Semaphore();
00716
00730 void wait(void);
00731
00743 bool tryWait(void);
00744
00756 void post(void);
00757
00758
00764 #ifndef WIN32
00765 #ifndef __CYGWIN32__
00766 int getValue(void);
00767 #endif
00768 #endif
00769 };
00770
00790 class __EXPORT SemaphoreLock
00791 {
00792 private:
00793 Semaphore& sem;
00794
00795 public:
00799 SemaphoreLock( Semaphore& _sem ) : sem( _sem )
00800 { sem.wait(); }
00804
00805 ~SemaphoreLock()
00806 { sem.post(); }
00807 };
00808
00822 class __EXPORT Event
00823 {
00824 private:
00825 #ifndef WIN32
00826 pthread_mutex_t _mutex;
00827 pthread_cond_t _cond;
00828 bool _signaled;
00829 int _count;
00830 #else
00831 HANDLE cond;
00832 #endif
00833
00834 public:
00835 Event();
00836
00837 virtual ~Event();
00838
00845 void reset(void);
00846
00850 void signal(void);
00851
00860 bool wait(timeout_t timer);
00861 bool wait(void);
00862 };
00863
00864
01046 class __EXPORT Thread
01047 {
01048 public:
01052 typedef enum Throw {
01053 throwNothing,
01054 throwObject,
01055 throwException
01056 } Throw;
01057
01061 typedef enum Cancel
01062 {
01063 cancelInitial=0,
01064 cancelDeferred=1,
01065 cancelImmediate,
01066 cancelDisabled,
01067 cancelManual,
01069 cancelDefault=cancelDeferred
01071 } Cancel;
01072
01076 typedef enum Suspend
01077 {
01078 suspendEnable,
01079 suspendDisable
01080 } Suspend;
01081
01082 #ifndef WIN32
01083
01084 friend class PosixThread;
01085 #endif
01086
01087 friend class DummyThread;
01088 private:
01089 friend class Cancellation;
01090 friend class postream_type;
01091 friend class Slog;
01092
01093 Semaphore joinSem;
01094 static Thread* _main;
01095
01096 Thread *_parent;
01097 Cancel _cancel;
01098 Semaphore *_start;
01099
01100
01101 friend class ThreadImpl;
01102 class ThreadImpl* priv;
01103
01104 public:
01105 static Thread *get(void);
01106
01107 private:
01108 #ifdef WIN32
01109 static unsigned __stdcall Execute(Thread *th);
01110 #endif
01111
01112
01113 void close();
01114
01115 private:
01116 char _name[32];
01117 static size_t _autostack;
01118
01119 #ifdef WIN32
01120 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01121 #endif
01122
01123 protected:
01131 void setName(const char *text);
01132
01142 virtual void run(void) = 0;
01143
01165 virtual void final(void)
01166 {return;};
01167
01179 virtual void initial(void)
01180 {return;};
01181
01191 virtual void* getExtended(void)
01192 {return NULL;};
01193
01201 virtual void notify(Thread*)
01202 {return;};
01203
01209 void exit(void);
01210
01214 void sync(void);
01215
01219 bool testCancel(void);
01220
01230 void setCancel(Cancel mode);
01231
01239 void setSuspend(Suspend mode);
01240
01249 void terminate(void);
01250
01254 inline void clrParent(void)
01255 {_parent = NULL;};
01256
01257 public:
01266 Thread(bool isMain);
01267
01279 Thread(int pri = 0, size_t stack = 0);
01280
01281 #ifndef WIN32
01282
01290 Thread(const Thread &th);
01291 #endif
01292
01299 virtual ~Thread();
01300
01306 static void setStack(size_t size = 0)
01307 {_autostack = size;};
01308
01318 static void sleep(timeout_t msec);
01319
01324 static void yield(void);
01325
01338 int start(Semaphore *start = 0);
01339
01348 int detach(Semaphore *start = 0);
01349
01356 inline Thread *getParent(void)
01357 {return _parent;};
01358
01365 void suspend(void);
01366
01370 void resume(void);
01371
01378 inline Cancel getCancel(void)
01379 {return _cancel;};
01380
01387 bool isRunning(void);
01388
01394 bool isDetached(void);
01395
01399 void join(void);
01400
01407 bool isThread(void);
01408
01414 cctid_t getId(void) const;
01415
01422 const char *getName(void)
01423 {return _name;};
01424
01430 static Throw getException(void);
01431
01437 static void setException(Throw mode);
01438
01445 friend inline void operator++(Thread &th)
01446 {if (th._start) th._start->post();};
01447
01448 friend inline void operator--(Thread &th)
01449 {if (th._start) th._start->wait();};
01450
01451 #ifdef WIN32
01452 bool isCancelled();
01453
01454 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01455 #endif
01456
01464 static Cancel enterCancel(void);
01465
01471 static void exitCancel(Cancel cancel);
01472 };
01473
01483 class __EXPORT Cancellation
01484 {
01485 private:
01486 Thread::Cancel prior;
01487
01488 public:
01489 Cancellation(Thread::Cancel cancel);
01490 ~Cancellation();
01491 };
01492
01493 #if !defined(WIN32) && !defined(__MINGW32__)
01494 typedef int signo_t;
01495
01496 class PosixThread: public Thread
01497 {
01498 private:
01499 #ifndef WIN32
01500
01501 friend class ThreadImpl;
01502 friend class Thread;
01503 #endif
01504 #ifndef CCXX_SIG_THREAD_ALARM
01505 static PosixThread *_timer;
01506 static Mutex _arm;
01507 #endif
01508
01509 time_t _alarm;
01510 static void signalThread(Thread* th,signo_t signo);
01511 protected:
01512
01519 inline void signalParent(signo_t signo)
01520 { signalThread(_parent,signo); };
01521
01528 inline void signalMain(signo_t signo)
01529 { signalThread(_main,signo);};
01530
01535 virtual void onTimer(void)
01536 {return;};
01537
01542 virtual void onHangup(void)
01543 {return;};
01544
01549 virtual void onException(void)
01550 {return;};
01551
01556 virtual void onDisconnect(void)
01557 {return;};
01558
01563 virtual void onPolling(void)
01564 {return;};
01565
01572 virtual void onSignal(int)
01573 {return;};
01574
01587 void setTimer(timeout_t timer, bool periodic = false);
01588
01595 timeout_t getTimer(void) const;
01596
01602 void endTimer(void);
01603
01604 #if defined(HAVE_SIGWAIT) || defined(HAVE_SIGWAIT2)
01605
01611 void waitSignal(signo_t signo);
01612 #endif
01613
01620 void setSignal(int signo, bool active);
01621
01628 pthread_attr_t *getPthreadAttrPtr(void);
01629
01634 pthread_t getPthreadId(void);
01635
01636 public:
01637
01638 PosixThread(int pri = 0, size_t stack = 0);
01639
01645 inline void signalThread(int signo)
01646 {signalThread(this, signo);};
01647
01654 static void sigInstall(int signo);
01655 };
01656 #endif
01657
01672 class __EXPORT ThreadKey
01673 {
01674 private:
01675 #ifndef WIN32
01676 pthread_key_t key;
01677 typedef void (*TDestruct)(void*);
01678 friend class ThreadImpl;
01679 ThreadKey(TDestruct destruct);
01680 #else
01681 DWORD key;
01682 #endif
01683
01684 public:
01688 ThreadKey();
01692 virtual ~ThreadKey();
01700 void *getKey(void);
01708 void setKey(void *);
01709 };
01710
01721 class __EXPORT TimerPort
01722 {
01723 #ifndef WIN32
01724 struct timeval timer;
01725 #else
01726 DWORD timer;
01727 #endif
01728 bool active;
01729
01730 public:
01737 TimerPort();
01738
01747 void setTimer(timeout_t timeout = 0);
01748
01758 void incTimer(timeout_t timeout);
01759
01765 void endTimer(void);
01766
01778 timeout_t getTimer(void) const;
01779
01789 timeout_t getElapsed(void) const;
01790 };
01791
01792
01793
01794
01795 #if !defined(WIN32)
01796
01797
01798 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01799
01800 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01801 void wait(signo_t signo);
01802 #endif
01803
01804 #endif // !WIN32
01805
01806 #ifdef USE_POLL
01807
01815 class Poller
01816 {
01817 private:
01818 int nufds;
01819 pollfd *ufds;
01820
01821 public:
01822 Poller();
01823
01824 virtual ~Poller();
01825
01833 pollfd *getList(int cnt);
01834
01840 inline pollfd *getList(void)
01841 {return ufds;};
01842 };
01843 #endif
01844
01845 inline Thread *getThread(void)
01846 {return Thread::get();}
01847
01877 class __EXPORT SysTime
01878 {
01879 private:
01880 static Mutex timeLock;
01881
01882 protected:
01883 inline static void lock(void)
01884 {timeLock.enterMutex();}
01885
01886 inline static void unlock(void)
01887 {timeLock.leaveMutex();}
01888
01889 public:
01890 static time_t getTime(time_t *tloc = NULL);
01891 static time_t time(time_t *tloc)
01892 { return getTime(tloc); };
01893
01894 static int getTimeOfDay(struct timeval *tp);
01895 static int gettimeofday(struct timeval *tp, struct timezone *tzp)
01896 { return getTimeOfDay(tp); };
01897
01898 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
01899 static struct tm *locatime(const time_t *clock, struct tm *result)
01900 { return getLocalTime(clock, result); };
01901
01902 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
01903 static struct tm *gmtime(const time_t *clock, struct tm *result)
01904 { return getGMTTime(clock, result);};
01905 };
01906
01907 #ifndef HAVE_LOCALTIME_R
01908
01909 inline struct tm *localtime_r(const time_t *t, struct tm *b)
01910 {return SysTime::getLocalTime(t, b);};
01911 inline char *ctime_r(const time_t *t, char *buf)
01912 {return ctime(t);};
01913 inline struct tm *gmtime_r(const time_t *t, struct tm *b) \
01914 {return SysTime::getGMTTime(t, b);};
01915 inline char *asctime_r(const struct tm *tm, char *b) \
01916 {return asctime(tm);};
01917
01918 #endif
01919
01920 #ifdef CCXX_NAMESPACES
01921 }
01922 #endif
01923
01924 #endif
01925