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 #ifndef CCXX_EXCEPTION_H_
00058 #include <cc++/exception.h>
00059 #endif
00060
00061 #ifndef WIN32
00062 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00063 #define CCXX_SYSV_SEMAPHORES
00064 #endif
00065
00066 #ifndef HAVE_PTHREAD_H
00067 #include <pthread.h>
00068 #ifndef CCXX_SYSV_SEMAPHORES
00069 #include <semaphore.h>
00070 #endif
00071 #endif
00072 #endif // !WIN32
00073
00074 #undef CCXX_USE_WIN32_ATOMIC
00075 #ifndef WIN32
00076 #include <time.h>
00077 #include <signal.h>
00078 #include <unistd.h>
00079
00080 #ifdef _THR_UNIXWARE
00081 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00082 #endif
00083
00084 typedef pthread_t cctid_t;
00085 typedef unsigned long timeout_t;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 #else // WIN32
00097 typedef DWORD cctid_t;
00098 typedef DWORD timeout_t;
00099
00100 #define MAX_SEM_VALUE 1000000
00101 #define CCXX_USE_WIN32_ATOMIC 1
00102 #if defined(__CYGWIN32__)
00103
00104 #else
00105 #if _MSC_VER < 1300
00106 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00107 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00108 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00109 #endif
00110 #endif
00111
00112 #endif // !WIN32
00113
00114 #ifdef CCXX_NAMESPACES
00115 namespace ost {
00116 #endif
00117
00118 class CCXX_CLASS_EXPORT Thread;
00119 class CCXX_CLASS_EXPORT ThreadKey;
00120
00121 #define TIMEOUT_INF ~((timeout_t) 0)
00122
00123 #define ENTER_CRITICAL enterMutex();
00124 #define LEAVE_CRITICAL leaveMutex();
00125 #define ENTER_DEFERRED setCancel(cancelDeferred);
00126 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00127
00128 #ifndef WIN32
00129
00130
00131
00132
00133
00134
00135 #undef sleep
00136 #define psleep(x) (sleep)(x)
00137
00138 #endif // !WIN32
00139
00140 #undef Yield
00141
00142 #ifdef WIN32
00143 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00144 #endif
00145
00146 class Conditional;
00147 class CCXX_CLASS_EXPORT Event;
00148
00192 class CCXX_CLASS_EXPORT Mutex
00193 {
00194 friend class Conditional;
00195 friend class Event;
00196 private:
00197 #ifndef WIN32
00198 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00199 volatile int _level;
00200 volatile Thread *_tid;
00201 #endif
00202
00203
00204
00205
00206
00207
00208
00209
00210 pthread_mutex_t _mutex;
00211 #else
00212 HANDLE mutex;
00213 #endif
00214
00215 public:
00219 Mutex();
00220
00226 virtual ~Mutex();
00227
00235 void enterMutex(void);
00236
00247 bool tryEnterMutex(void);
00248
00259 void leaveMutex(void);
00260 };
00261
00283 class MutexLock
00284 {
00285 private:
00286 Mutex& mutex;
00287 public:
00291 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00292 { mutex.enterMutex(); }
00296
00297 ~MutexLock()
00298 { mutex.leaveMutex(); }
00299 };
00300
00309 class CCXX_CLASS_EXPORT ThreadLock
00310 {
00311 private:
00312 #ifdef HAVE_PTHREAD_RWLOCK
00313 pthread_rwlock_t _lock;
00314 #else
00315 Mutex mutex;
00316 #endif
00317
00318 public:
00322 ThreadLock();
00323
00327 virtual ~ThreadLock();
00328
00332 void readLock(void);
00333
00337 void writeLock(void);
00338
00344 bool tryReadLock(void);
00345
00351 bool tryWriteLock(void);
00352
00356 void unlock(void);
00357 };
00358
00368 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00369 {
00370 private:
00371 int counter;
00372
00373 public:
00374 MutexCounter();
00375 MutexCounter(int initial);
00376
00377 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00378 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00379 };
00380
00391 class CCXX_CLASS_EXPORT AtomicCounter
00392 {
00393 #ifndef CCXX_USE_WIN32_ATOMIC
00394 private:
00395 #ifdef HAVE_ATOMIC
00396 atomic_t atomic;
00397 #else
00398 int counter;
00399 Mutex lock;
00400 #endif
00401
00402 public:
00406 AtomicCounter();
00407
00413 AtomicCounter(int value);
00414
00415 int operator++(void);
00416 int operator--(void);
00417 int operator+=(int change);
00418 int operator-=(int change);
00419 int operator+(int change);
00420 int operator-(int change);
00421 int operator=(int value);
00422 bool operator!(void);
00423 operator int();
00424 #else
00425 private:
00426 long atomic;
00427
00428 public:
00429 inline AtomicCounter()
00430 {atomic = 0;};
00431
00432 inline AtomicCounter(int value)
00433 {atomic = value;};
00434
00435 inline int operator++(void)
00436 {return InterlockedIncrement(&atomic);};
00437
00438 inline int operator--(void)
00439 {return InterlockedDecrement(&atomic);};
00440
00441 int operator+=(int change);
00442
00443 int operator-=(int change);
00444
00445 inline int operator+(int change)
00446 {return atomic + change;};
00447
00448 inline int operator-(int change)
00449 {return atomic - change;};
00450
00451 inline int operator=(int value)
00452 {return InterlockedExchange(&atomic, value);};
00453
00454 inline bool operator!(void)
00455 {return (atomic == 0) ? true : false;};
00456
00457 inline operator int()
00458 {return atomic;};
00459 #endif
00460 };
00461
00462 #ifndef WIN32
00463
00483 class Conditional : public Mutex
00484 {
00485 private:
00486 pthread_cond_t _cond;
00487
00488 public:
00492 Conditional();
00493
00497 virtual ~Conditional();
00498
00504 void signal(bool broadcast);
00505
00509 void wait(timeout_t timer = 0);
00510 };
00511 #endif
00512
00530 class CCXX_CLASS_EXPORT Semaphore
00531 {
00532 private:
00533 #ifndef WIN32
00534 #ifdef CCXX_SYSV_SEMAPHORES
00535 int _semaphore;
00536 #else
00537 sem_t _semaphore;
00538 #endif
00539 #else // WIN32
00540 HANDLE semObject;
00541 #endif // !WIN32
00542
00543 public:
00552 Semaphore(size_t resource = 0);
00553
00560 virtual ~Semaphore();
00561
00575 void wait(void);
00576
00588 bool tryWait(void);
00589
00601 void post(void);
00602
00603
00609 #ifndef WIN32
00610 #ifndef __CYGWIN32__
00611 int getValue(void);
00612 #endif
00613 #endif
00614 };
00615
00629 class CCXX_CLASS_EXPORT Event
00630 {
00631 private:
00632 #ifndef WIN32
00633 Mutex mutex;
00634 pthread_cond_t _cond;
00635 bool _signaled;
00636 int _count;
00637 #else
00638 HANDLE cond;
00639 #endif
00640
00641 public:
00642 Event();
00643
00644 virtual ~Event();
00645
00652 void reset(void);
00653
00657 void signal(void);
00658
00667 bool wait(timeout_t timer);
00668 bool wait(void);
00669 };
00670
00692 class CCXX_CLASS_EXPORT Buffer
00693 {
00694 private:
00695 Mutex lock_head, lock_tail;
00696 Semaphore size_head, size_tail;
00697 size_t _size;
00698 size_t _used;
00699
00700 protected:
00706 virtual int onPeek(void *buf) = 0;
00712 virtual int onWait(void *buf) = 0;
00718 virtual int onPost(void *buf) = 0;
00719
00720 public:
00725 Buffer(size_t capacity);
00730 virtual ~Buffer()
00731 {return;};
00732
00737 inline size_t getSize(void)
00738 {return _size;};
00739
00746 inline size_t getUsed(void)
00747 {return _used;};
00748
00757 int wait(void *buf);
00758
00766 int post(void *buf);
00767
00774 int peek(void *buf);
00775
00780 virtual bool isValid(void)
00781 {return true;};
00782 };
00783
00791 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00792 {
00793 private:
00794 char *buf, *head, *tail;
00795 size_t objsize;
00796
00797 protected:
00803 int onPeek(void *buf);
00804
00810 int onWait(void *buf);
00811
00817 int onPost(void *buf);
00818
00819 public:
00827 FixedBuffer(size_t capacity, size_t objsize);
00828
00835 FixedBuffer(const FixedBuffer &fb);
00836
00840 virtual ~FixedBuffer();
00841
00842 FixedBuffer &operator=(const FixedBuffer &fb);
00843
00844 bool isValid(void);
00845 };
00846
01026 class CCXX_CLASS_EXPORT Thread
01027 {
01028 public:
01032 typedef enum Throw {
01033 throwNothing,
01034 throwObject,
01035 throwException
01036 } Throw;
01037
01041 typedef enum Cancel
01042 {
01043 cancelInitial=0,
01044 cancelDeferred=1,
01045 cancelImmediate,
01046 cancelDisabled,
01047 cancelManual,
01049 cancelDefault=cancelDeferred
01051 } Cancel;
01052
01056 typedef enum Suspend
01057 {
01058 suspendEnable,
01059 suspendDisable
01060 } Suspend;
01061
01062 #ifndef WIN32
01063
01064 friend class PosixThread;
01065 #endif
01066
01067 friend class DummyThread;
01068 private:
01069 friend class Slog;
01070
01071 static Thread* _main;
01072
01073 Thread *_parent;
01074 enum Cancel _cancel;
01075 Semaphore *_start;
01076
01077
01078 friend class ThreadImpl;
01079 class ThreadImpl* priv;
01080
01081 #ifndef WIN32
01082 friend Thread *getThread(void);
01083 #else
01084 static unsigned __stdcall Execute(Thread *th);
01085 #endif
01086
01087
01088 void close();
01089
01090 protected:
01100 virtual void run(void) = 0;
01101
01118 virtual void final(void)
01119 {return;};
01120
01132 virtual void initial(void)
01133 {return;};
01134
01144 virtual void* getExtended(void)
01145 {return NULL;};
01146
01154 virtual void notify(Thread*)
01155 {return;};
01156
01162 void exit(void);
01163
01167 bool testCancel(void);
01168
01178 void setCancel(Cancel mode);
01179
01187 void setSuspend(Suspend mode);
01188
01197 void terminate(void);
01198
01202 inline void clrParent(void)
01203 {_parent = NULL;};
01204
01205 #ifdef WIN32
01206
01207 DWORD waitHandle(HANDLE obj, timeout_t timeout);
01208 #endif
01209
01210 public:
01219 Thread(bool isMain);
01220
01232 Thread(int pri = 0, size_t stack = 0);
01233
01234 #ifndef WIN32
01235
01243 Thread(const Thread &th);
01244 #endif
01245
01252 virtual ~Thread();
01253
01263 static void sleep(timeout_t msec);
01264
01269 static void yield(void);
01270
01283 int start(Semaphore *start = 0);
01284
01293 int detach(Semaphore *start = 0);
01294
01301 inline Thread *getParent(void)
01302 {return _parent;};
01303
01310 void suspend(void);
01311
01315 void resume(void);
01316
01323 inline Cancel getCancel(void)
01324 {return _cancel;};
01325
01332 bool isRunning(void);
01333
01340 bool isThread(void);
01341
01347 friend CCXX_EXPORT(Throw) getException(void);
01348
01354 friend CCXX_EXPORT(void) setException(Throw mode);
01355
01362 friend inline void operator++(Thread &th)
01363 {if (th._start) th._start->post();};
01364
01365 friend inline void operator--(Thread &th)
01366 {if (th._start) th._start->wait();};
01367
01368 #ifdef WIN32
01369
01370 bool isCancelled();
01371
01372 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01373 #endif
01374 };
01375
01381 CCXX_EXPORT(Thread*) getThread(void);
01383 CCXX_EXPORT(Thread::Throw) getException(void);
01385 CCXX_EXPORT(void) setException(Thread::Throw mode);
01386
01387 #if !defined(WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__)
01388 typedef int signo_t;
01389
01390 class PosixThread: public Thread
01391 {
01392 private:
01393 #ifndef WIN32
01394
01395 friend class ThreadImpl;
01396 friend class Thread;
01397 #endif
01398 #ifndef CCXX_SIG_THREAD_ALARM
01399 static PosixThread *_timer;
01400 static Mutex _arm;
01401 #endif
01402
01403 time_t _alarm;
01404 static void signalThread(Thread* th,signo_t signo);
01405 protected:
01406
01413 inline void signalParent(signo_t signo)
01414 { signalThread(_parent,signo); };
01415
01422 inline void signalMain(signo_t signo)
01423 { signalThread(_main,signo);};
01424
01429 virtual void onTimer(void)
01430 {return;};
01431
01436 virtual void onHangup(void)
01437 {return;};
01438
01443 virtual void onException(void)
01444 {return;};
01445
01450 virtual void onDisconnect(void)
01451 {return;};
01452
01457 virtual void onPolling(void)
01458 {return;};
01459
01466 virtual void onSignal(int)
01467 {return;};
01468
01478 void setTimer(timeout_t timer);
01479
01486 timeout_t getTimer(void) const;
01487
01493 void endTimer(void);
01494
01501 void waitSignal(signo_t signo);
01502
01509 void setSignal(int signo, bool active);
01510 public:
01511
01512 CCXX_MEMBER_EXPORT(CCXX_EMPTY) PosixThread(int pri = 0, size_t stack = 0);
01513
01519 inline void signalThread(int signo)
01520 {signalThread(this, signo);};
01521
01528 friend void sigInstall(int signo);
01529 };
01530 #endif
01531
01546 class ThreadKey
01547 {
01548 private:
01549 #ifndef WIN32
01550 pthread_key_t key;
01551 typedef void (*TDestruct)(void*);
01552 friend class ThreadImpl;
01553 ThreadKey(TDestruct destruct);
01554 #else
01555 DWORD key;
01556 #endif
01557
01558 public:
01562 ThreadKey();
01566 virtual ~ThreadKey();
01574 void *getKey(void);
01582 void setKey(void *);
01583 };
01584
01595 class CCXX_CLASS_EXPORT TimerPort
01596 {
01597 #ifndef WIN32
01598 struct timeval timer;
01599 #else
01600 DWORD timer;
01601 #endif
01602 bool active;
01603
01604 public:
01611 TimerPort();
01612
01621 void setTimer(timeout_t timeout = 0);
01622
01632 void incTimer(timeout_t timeout);
01633
01639 void endTimer(void);
01640
01651 timeout_t getTimer(void) const;
01652
01661 timeout_t getElapsed(void) const;
01662 };
01663
01665 inline int get(Buffer &b, void *o)
01666 {return b.wait(o);};
01667
01669 inline int put(Buffer &b, void *o)
01670 {return b.post(o);};
01671
01673 inline int peek(Buffer &b, void *o)
01674 {return b.peek(o);};
01675
01676
01677
01678 #if !defined(WIN32)
01679
01680
01681 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01682
01683 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01684 void wait(signo_t signo);
01685 #endif
01686
01687 #endif // !WIN32
01688
01689
01690 #ifndef WIN32
01691 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01692 #if defined(HAVE_SYS_STREAM_H)
01693 #if defined(__linux__)
01694 #define CCXX_USE_POLL 1
01695 #endif
01696 #else
01697 #define CCXX_USE_POLL 1
01698 #endif
01699 #endif
01700
01701 #ifdef CCXX_USE_POLL
01702
01710 class Poller
01711 {
01712 private:
01713 int nufds;
01714 pollfd *ufds;
01715
01716 public:
01717 Poller();
01718
01719 virtual ~Poller();
01720
01728 pollfd *getList(int cnt);
01729
01735 inline pollfd *getList(void)
01736 {return ufds;};
01737 };
01738 #endif
01739 #endif // !WIN32
01740
01741 #ifdef COMMON_STD_EXCEPTION
01742
01748 class ThrException : public Exception
01749 {
01750 public:
01751 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01752 };
01753
01760 class SyncException : public ThrException
01761 {
01762 public:
01763 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01764 };
01765
01766 class InterruptException : public ThrException
01767 {
01768 public:
01769 InterruptException() : ThrException("interrupted") {};
01770 };
01771
01772 #endif
01773
01774 #ifdef CCXX_NAMESPACES
01775 };
01776 #endif
01777
01778 #endif
01779