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
00041 #ifndef __CCXX_THREAD_H__
00042 #define __CCXX_THREAD_H__
00043
00044 #ifndef WIN32
00045 #define __CCXX_POSIX
00046 #endif // !WIN32
00047
00048 #ifndef CCXX_CONFIG_H_
00049 #include <cc++/config.h>
00050 #endif
00051
00052 #ifndef __CCXX_EXCEPTION_H__
00053 #include <cc++/exception.h>
00054 #endif
00055
00056 #ifndef WIN32
00057 #if defined(__FreeBSD__) && __FreeBSD__ <= 3
00058 #define _SYSV_SEMAPHORES
00059 #endif
00060
00061 #ifndef HAVE_PTHREAD_H
00062 #include <pthread.h>
00063 #ifndef _SYSV_SEMAPHORES
00064 #include <semaphore.h>
00065 #endif
00066 #endif
00067 #endif // !WIN32
00068
00069 #include <setjmp.h>
00070
00071 #ifndef WIN32
00072 #include <time.h>
00073 #include <signal.h>
00074 #include <unistd.h>
00075
00076 #ifdef __linux__
00077 #define _SIG_THREAD_ALARM
00078 #endif
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 #else // WIN32
00087 typedef DWORD cctid_t;
00088 typedef DWORD timeout_t;
00089
00090 #define MAX_SEM_VALUE 1000000
00091 #if defined(__MINGW32__) || defined(__CYGWIN32__)
00092 #include <Windows32/CommonFunctions.h>
00093 #else
00094 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00095 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00096 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00097 #endif
00098
00099 #endif // !WIN32
00100
00101 #ifdef CCXX_NAMESPACES
00102 namespace ost {
00103 #endif
00104
00105 enum throw_t {
00106 THROW_NOTHING,
00107 THROW_OBJECT,
00108 THROW_EXCEPTION
00109 };
00110 typedef enum throw_t throw_t;
00111 class Thread;
00112
00113 #define TIMEOUT_INF ~((timeout_t) 0)
00114
00115 #define ENTER_CRITICAL EnterMutex();
00116 #define LEAVE_CRITICAL LeaveMutex();
00117 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00118 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00119
00120 enum thread_cancel_t
00121 {
00122 THREAD_CANCEL_INITIAL=0,
00123 THREAD_CANCEL_DEFERRED=1,
00124 THREAD_CANCEL_IMMEDIATE,
00125 THREAD_CANCEL_DISABLED,
00126 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED
00127 };
00128 typedef enum thread_cancel_t thread_cancel_t;
00129
00130 enum thread_suspend_t
00131 {
00132 THREAD_SUSPEND_ENABLE,
00133 THREAD_SUSPEND_DISABLE
00134 };
00135 typedef enum thread_suspend_t thread_suspend_t;
00136
00137 #ifndef WIN32
00138
00139
00140
00141
00142
00143
00144 #undef sleep
00145 #define psleep(x) (sleep)(x)
00146
00147 static RETSIGTYPE ccxx_sigsuspend(int);
00148 extern "C" void execHandler(Thread *th);
00149
00150 #endif // !WIN32
00151
00152
00153 CCXX_EXPORT(Thread*) getThread(void);
00154 CCXX_EXPORT(throw_t) getException(void);
00155 CCXX_EXPORT(void) setException(throw_t mode);
00156 CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
00157 CCXX_EXPORT(void) ccxx_yield(void);
00158
00159 #undef Yield
00160 #define sleep(x) ccxx_sleep((x) * 1000)
00161 #define yield() ccxx_yield()
00162
00163 #ifdef WIN32
00164 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00165 #endif
00166
00167 class Conditional;
00168 class CCXX_CLASS_EXPORT Event;
00169
00213 class CCXX_CLASS_EXPORT Mutex
00214 {
00215 friend class Conditional;
00216 friend class Event;
00217 private:
00218 #ifndef WIN32
00219 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00220 volatile int _level;
00221 volatile Thread *_tid;
00222 #endif
00223
00231 pthread_mutex_t _mutex;
00232 #else
00233 HANDLE mutex;
00234 #endif
00235
00236 public:
00240 Mutex();
00241
00247 virtual ~Mutex();
00248
00256 void EnterMutex(void);
00257
00268 bool TryEnterMutex(void);
00269
00280 void LeaveMutex(void);
00281 };
00282
00304 class MutexLock
00305 {
00306 private:
00307 Mutex& mutex;
00308 public:
00312 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00313 { mutex.EnterMutex(); }
00317
00318 ~MutexLock()
00319 { mutex.LeaveMutex(); }
00320 };
00321
00330 class CCXX_CLASS_EXPORT ThreadLock
00331 {
00332 private:
00333 #ifdef HAVE_PTHREAD_RWLOCK
00334 pthread_rwlock_t _lock;
00335 #else
00336 Mutex mutex;
00337 #endif
00338
00339 public:
00343 ThreadLock();
00344
00348 virtual ~ThreadLock();
00349
00353 void ReadLock(void);
00354
00358 void WriteLock(void);
00359
00365 bool TryReadLock(void);
00366
00372 bool TryWriteLock(void);
00373
00377 void Unlock(void);
00378 };
00379
00389 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00390 {
00391 private:
00392 int counter;
00393
00394 public:
00395 MutexCounter();
00396 MutexCounter(int initial);
00397
00398 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00399 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00400 };
00401
00412 class CCXX_CLASS_EXPORT AtomicCounter
00413 {
00414 #ifndef WIN32
00415 private:
00416 #ifdef HAVE_ATOMIC
00417 atomic_t atomic;
00418 #else
00419 int counter;
00420 Mutex lock;
00421 #endif
00422
00423 public:
00427 AtomicCounter();
00428
00434 AtomicCounter(int value);
00435
00436 int operator++(void);
00437 int operator--(void);
00438 int operator+=(int change);
00439 int operator-=(int change);
00440 int operator+(int change);
00441 int operator-(int change);
00442 int operator=(int value);
00443 bool operator!(void);
00444 operator int();
00445 #else
00446 private:
00447 long atomic;
00448
00449 public:
00450 inline AtomicCounter()
00451 {atomic = 0;};
00452
00453 inline AtomicCounter(int value)
00454 {atomic = value;};
00455
00456 inline int operator++(void)
00457 {return InterlockedIncrement(&atomic);};
00458
00459 inline int operator--(void)
00460 {return InterlockedDecrement(&atomic);};
00461
00462 int operator+=(int change);
00463
00464 int operator-=(int change);
00465
00466 inline int operator+(int change)
00467 {return atomic + change;};
00468
00469 inline int operator-(int change)
00470 {return atomic - change;};
00471
00472 inline int operator=(int value)
00473 {return InterlockedExchange(&atomic, value);};
00474
00475 inline bool operator!(void)
00476 {return (atomic == 0) ? true : false;};
00477
00478 inline operator int()
00479 {return atomic;};
00480 #endif
00481 };
00482
00483
00484 #ifndef WIN32
00485
00495 class Conditional : public Mutex
00496 {
00497 private:
00498 pthread_cond_t _cond;
00499
00500 public:
00504 Conditional();
00505
00509 virtual ~Conditional();
00510
00516 void Signal(bool broadcast);
00517
00521 void Wait(timeout_t timer = 0);
00522 };
00523 #endif
00524
00542 class CCXX_CLASS_EXPORT Semaphore
00543 {
00544 private:
00545 #ifndef WIN32
00546 #ifdef _SYSV_SEMAPHORES
00547 int _semaphore;
00548 #else
00549 sem_t _semaphore;
00550 #endif
00551 #else // WIN32
00552 HANDLE semObject;
00553 #endif // !WIN32
00554
00555 public:
00564 Semaphore(size_t resource = 0);
00565
00572 virtual ~Semaphore();
00573
00587 void Wait(void);
00588
00600 bool TryWait(void);
00601
00613 void Post(void);
00614
00615
00621 #ifndef WIN32
00622 #ifndef __CYGWIN32__
00623 int getValue(void);
00624 #endif
00625 #endif
00626 };
00627
00641 class CCXX_CLASS_EXPORT Event
00642 {
00643 private:
00644 #ifndef WIN32
00645 Mutex mutex;
00646 pthread_cond_t _cond;
00647 bool _signaled;
00648 int _count;
00649 #else
00650 HANDLE cond;
00651 #endif
00652
00653 public:
00654 Event();
00655
00656 virtual ~Event();
00657
00664 void Reset(void);
00665
00669 void Signal(void);
00670
00679 bool Wait(timeout_t timer);
00680 bool Wait(void);
00681 };
00682
00704 class CCXX_CLASS_EXPORT Buffer
00705 {
00706 private:
00707 Mutex lock_head, lock_tail;
00708 Semaphore size_head, size_tail;
00709 size_t _size;
00710 size_t _used;
00711
00712 protected:
00718 virtual int OnPeek(void *buf) = 0;
00724 virtual int OnWait(void *buf) = 0;
00730 virtual int OnPost(void *buf) = 0;
00731
00732 public:
00737 Buffer(size_t capacity);
00742 virtual ~Buffer()
00743 {return;};
00744
00749 inline size_t getSize(void)
00750 {return _size;};
00751
00758 inline size_t getUsed(void)
00759 {return _used;};
00760
00769 int Wait(void *buf);
00770
00778 int Post(void *buf);
00779
00786 int Peek(void *buf);
00787
00792 virtual bool isValid(void)
00793 {return true;};
00794 };
00795
00803 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00804 {
00805 private:
00806 char *buf, *head, *tail;
00807 size_t objsize;
00808
00809 protected:
00815 int OnPeek(void *buf);
00816
00822 int OnWait(void *buf);
00823
00829 int OnPost(void *buf);
00830
00831 public:
00839 FixedBuffer(size_t capacity, size_t objsize);
00840
00847 FixedBuffer(const FixedBuffer &fb);
00848
00852 virtual ~FixedBuffer();
00853
00854 FixedBuffer &operator=(const FixedBuffer &fb);
00855
00856 bool isValid(void);
00857 };
00858
01006 class Thread
01007 {
01008 #ifndef WIN32
01009 friend class PosixThread;
01010 friend RETSIGTYPE ccxx_sigsuspend(int);
01011 #endif
01012 private:
01013 friend class Slog;
01014
01015 static Thread *_main;
01016
01017 Thread *_parent;
01018 #ifndef WIN32
01019 pthread_t _tid;
01020 pthread_attr_t _attr;
01021 AtomicCounter _suspendcount;
01022 #else
01023 DWORD _tid;
01024 HANDLE _cancellation;
01025 #endif
01026 thread_cancel_t _cancel;
01027 jmp_buf _env;
01028 Semaphore *_start;
01029 int _msgpos;
01030 char _msgbuf[128];
01031 throw_t _throw;
01032
01033 #ifndef WIN32
01034 friend void execHandler(Thread *th);
01035 friend Thread *getThread(void);
01036 #else
01037 bool _active:1;
01038 bool _suspendEnable:1;
01039 static unsigned __stdcall Execute(Thread *th);
01040 HANDLE _hThread;
01041 #endif
01042
01043 protected:
01053 virtual void Run(void) = 0;
01054
01067 CCXX_MEMBER_EXPORT(virtual void) Final(void)
01068 {return;};
01069
01080 CCXX_MEMBER_EXPORT(virtual void) Initial(void)
01081 {return;};
01082
01092 CCXX_MEMBER_EXPORT(virtual void*) getExtended(void)
01093 {return NULL;};
01094
01102 CCXX_MEMBER_EXPORT(virtual void) Notify(Thread *th)
01103 {return;};
01104
01114 CCXX_MEMBER_EXPORT(void) Sleep(timeout_t msec)
01115 #ifndef WIN32
01116 {ccxx_sleep(msec);}
01117 #endif
01118 ;
01119
01120
01126 inline void Exit(void)
01127 {longjmp(_env, 1);};
01128
01133 CCXX_MEMBER_EXPORT(void) Yield(void);
01134
01138 CCXX_MEMBER_EXPORT(void) testCancel(void);
01139
01148 CCXX_MEMBER_EXPORT(void) setCancel(thread_cancel_t mode);
01149
01157 CCXX_MEMBER_EXPORT(void) setSuspend(thread_suspend_t mode);
01158
01167 CCXX_MEMBER_EXPORT(void) Terminate(void);
01168
01172 inline void clrParent(void)
01173 {_parent = NULL;};
01174
01175 #ifdef WIN32
01176
01177 CCXX_MEMBER_EXPORT(DWORD) WaitHandle(HANDLE obj, timeout_t timeout);
01178 #endif
01179
01180 public:
01189 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(bool isMain);
01190
01203 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(int pri = 0, size_t stack = 0);
01204
01205
01206 #ifndef WIN32
01207
01214 Thread(const Thread &th);
01215 #endif
01216
01223 CCXX_MEMBER_EXPORT(virtual) ~Thread()
01224 {Terminate();};
01225
01238 CCXX_MEMBER_EXPORT(int) Start(Semaphore *start = 0);
01239
01248 CCXX_MEMBER_EXPORT(int) Detach(Semaphore *start = 0);
01249
01256 inline Thread *getParent(void)
01257 {return _parent;};
01258
01265 CCXX_MEMBER_EXPORT(void) Suspend(void);
01266
01270 CCXX_MEMBER_EXPORT(void) Resume(void);
01271
01278 inline thread_cancel_t getCancel(void)
01279 {return _cancel;};
01280
01287 bool isRunning(void)
01288 #ifdef WIN32
01289 {return (_tid != 0) ? true : false;}
01290 #endif
01291 ;
01292
01299 bool isThread(void)
01300 #ifdef WIN32
01301 {return ((_tid == GetCurrentThreadId())) ? true : false;}
01302 #endif
01303 ;
01304
01310 friend CCXX_EXPORT(throw_t) getException(void);
01311
01317 friend CCXX_EXPORT(void) setException(throw_t mode);
01318
01319
01326 friend inline void operator++(Thread &th)
01327 {th._start->Post();};
01328
01329 friend inline void operator--(Thread &th)
01330 {th._start->Wait();};
01331
01337 friend CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
01338
01342 friend CCXX_EXPORT(void) ccxx_yield(void);
01343
01344 #ifdef WIN32
01345
01346 inline bool isCancelled(void)
01347 {return waitThread(_cancellation, 0) == WAIT_OBJECT_0; };
01348
01349 inline bool isCancelled(timeout_t timer)
01350 {return waitThread(_cancellation, timer) == WAIT_OBJECT_0; };
01351
01352 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01353 #endif
01354 };
01355
01356 #ifndef WIN32
01357 extern "C" void sigHandler(int signo);
01358
01359 typedef int signo_t;
01360
01361 class PosixThread: public Thread
01362 {
01363 private:
01364 #ifndef WIN32
01365 friend void execHandler(Thread *th);
01366 #endif
01367 #ifndef _SIG_THREAD_ALARM
01368 static PosixThread *_timer;
01369 static Mutex _arm;
01370 #endif
01371
01372 time_t _alarm;
01373 friend void sigHandler(int signo);
01374 inline static void SignalThread(Thread* th,signo_t signo)
01375 {pthread_kill(th->_tid, signo);};
01376 protected:
01377
01384 inline void SignalParent(signo_t signo)
01385 { SignalThread(_parent,signo); };
01386
01393 inline void SignalMain(signo_t signo)
01394 { SignalThread(_main,signo);};
01395
01400 virtual void OnTimer(void)
01401 {return;};
01402
01407 virtual void OnHangup(void)
01408 {return;};
01409
01414 virtual void OnException(void)
01415 {return;};
01416
01421 virtual void OnDisconnect(void)
01422 {return;};
01423
01428 virtual void OnPolling(void)
01429 {return;};
01430
01437 virtual void OnSignal(int signo)
01438 {return;};
01439
01449 void setTimer(timeout_t timer);
01450
01457 timeout_t getTimer(void);
01458
01464 void endTimer(void);
01465
01472 void WaitSignal(signo_t signo);
01473
01480 void setSignal(int signo, bool mode);
01481 public:
01482
01488 inline void SignalThread(int signo)
01489 {SignalThread(this, signo);};
01490
01497 friend void siginstall(int signo);
01498 };
01499 #endif
01500
01515 class CCXX_CLASS_EXPORT ThreadKey
01516 {
01517 private:
01518 #ifndef WIN32
01519 pthread_key_t key;
01520 #else
01521 DWORD key;
01522 #endif
01523
01524 public:
01528 ThreadKey();
01532 virtual ~ThreadKey();
01540 void *getKey(void);
01548 void setKey(void *);
01549 };
01550
01561 class CCXX_CLASS_EXPORT TimerPort
01562 {
01563 #ifndef WIN32
01564 struct timeval timer;
01565 #else
01566 DWORD timer;
01567 #endif
01568 bool active;
01569
01570 public:
01577 TimerPort();
01578
01587 void setTimer(timeout_t timeout = 0);
01588
01598 void incTimer(timeout_t timeout);
01599
01605 void endTimer(void);
01606
01617 timeout_t getTimer(void);
01618
01627 timeout_t getElapsed(void);
01628 };
01629
01630 inline int get(Buffer &b, void *o)
01631 {return b.Wait(o);};
01632
01633 inline int put(Buffer &b, void *o)
01634 {return b.Post(o);};
01635
01636 inline int peek(Buffer &b, void *o)
01637 {return b.Peek(o);};
01638
01639
01640
01641 #ifndef WIN32
01642
01643
01644 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01645 void wait(signo_t signo);
01646
01655 void pdetach(void);
01656 #endif // !WIN32
01657
01658
01659 #ifndef WIN32
01660 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01661 #if defined(HAVE_SYS_STREAM_H)
01662 #if defined(__linux__)
01663 #define __CCXX_USE_POLL 1
01664 #endif
01665 #else
01666 #define __CCXX_USE_POLL 1
01667 #endif
01668 #endif
01669
01670 #ifdef __CCXX_USE_POLL
01671
01679 class Poller
01680 {
01681 private:
01682 int nufds;
01683 pollfd *ufds;
01684
01685 public:
01686 Poller();
01687
01688 virtual ~Poller();
01689
01697 pollfd *getList(int cnt);
01698
01704 inline pollfd *getList(void)
01705 {return ufds;};
01706 };
01707 #endif
01708 #endif // !WIN32
01709
01710 #ifdef COMMON_STD_EXCEPTION
01711
01717 class ThrException : public Exception
01718 {
01719 public:
01720 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01721 };
01722
01729 class SyncException : public ThrException
01730 {
01731 public:
01732 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01733 };
01734 #endif
01735
01736 #ifdef CCXX_NAMESPACES
01737 };
01738 #endif
01739
01740 #endif
01741