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 CCXX_SYSV_SEMAPHORES
00059 #endif
00060
00061 #ifndef HAVE_PTHREAD_H
00062 #include <pthread.h>
00063 #ifndef CCXX_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 CCXX_SIG_THREAD_ALARM
00078 #define CCXX_SIG_THREAD_STOPCONT
00079 #endif
00080
00081 #ifdef _THR_UNIXWARE
00082 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00083 #endif
00084
00085 typedef pthread_t cctid_t;
00086 typedef unsigned long timeout_t;
00087 #else // WIN32
00088 typedef DWORD cctid_t;
00089 typedef DWORD timeout_t;
00090
00091 #define MAX_SEM_VALUE 1000000
00092 #if defined(__MINGW32__) || defined(__CYGWIN32__)
00093 #include <Windows32/CommonFunctions.h>
00094 #else
00095 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00096 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00097 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00098 #endif
00099
00100 #endif // !WIN32
00101
00102 #ifdef CCXX_NAMESPACES
00103 namespace ost {
00104 #endif
00105
00106 enum throw_t {
00107 THROW_NOTHING,
00108 THROW_OBJECT,
00109 THROW_EXCEPTION
00110 };
00111 typedef enum throw_t throw_t;
00112 class Thread;
00113
00114 #define TIMEOUT_INF ~((timeout_t) 0)
00115
00116 #define ENTER_CRITICAL EnterMutex();
00117 #define LEAVE_CRITICAL LeaveMutex();
00118 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00119 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00120
00121 enum thread_cancel_t
00122 {
00123 THREAD_CANCEL_INITIAL=0,
00124 THREAD_CANCEL_DEFERRED=1,
00125 THREAD_CANCEL_IMMEDIATE,
00126 THREAD_CANCEL_DISABLED,
00127 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED
00128 };
00129 typedef enum thread_cancel_t thread_cancel_t;
00130
00131 enum thread_suspend_t
00132 {
00133 THREAD_SUSPEND_ENABLE,
00134 THREAD_SUSPEND_DISABLE
00135 };
00136 typedef enum thread_suspend_t thread_suspend_t;
00137
00138 #ifndef WIN32
00139
00140
00141
00142
00143
00144
00145 #undef sleep
00146 #define psleep(x) (sleep)(x)
00147
00148 #ifndef CCXX_SIG_THREAD_STOPCONT
00149 #ifndef _THR_SUNOS5
00150 static RETSIGTYPE ccxx_sigsuspend(int);
00151 #endif
00152 #endif
00153 extern "C" void execHandler(Thread *th);
00154
00155 #endif // !WIN32
00156
00157
00158 CCXX_EXPORT(Thread*) getThread(void);
00159 CCXX_EXPORT(throw_t) getException(void);
00160 CCXX_EXPORT(void) setException(throw_t mode);
00161 CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
00162 CCXX_EXPORT(void) ccxx_yield(void);
00163
00164 #undef Yield
00165 #define sleep(x) ccxx_sleep((x) * 1000)
00166 #define yield() ccxx_yield()
00167
00168 #ifdef WIN32
00169 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00170 #endif
00171
00172 class Conditional;
00173 class CCXX_CLASS_EXPORT Event;
00174
00218 class CCXX_CLASS_EXPORT Mutex
00219 {
00220 friend class Conditional;
00221 friend class Event;
00222 private:
00223 #ifndef WIN32
00224 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00225 volatile int _level;
00226 volatile Thread *_tid;
00227 #endif
00228
00236 pthread_mutex_t _mutex;
00237 #else
00238 HANDLE mutex;
00239 #endif
00240
00241 public:
00245 Mutex();
00246
00252 virtual ~Mutex();
00253
00261 void EnterMutex(void);
00262
00273 bool TryEnterMutex(void);
00274
00285 void LeaveMutex(void);
00286 };
00287
00309 class MutexLock
00310 {
00311 private:
00312 Mutex& mutex;
00313 public:
00317 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00318 { mutex.EnterMutex(); }
00322
00323 ~MutexLock()
00324 { mutex.LeaveMutex(); }
00325 };
00326
00335 class CCXX_CLASS_EXPORT ThreadLock
00336 {
00337 private:
00338 #ifdef HAVE_PTHREAD_RWLOCK
00339 pthread_rwlock_t _lock;
00340 #else
00341 Mutex mutex;
00342 #endif
00343
00344 public:
00348 ThreadLock();
00349
00353 virtual ~ThreadLock();
00354
00358 void ReadLock(void);
00359
00363 void WriteLock(void);
00364
00370 bool TryReadLock(void);
00371
00377 bool TryWriteLock(void);
00378
00382 void Unlock(void);
00383 };
00384
00394 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00395 {
00396 private:
00397 int counter;
00398
00399 public:
00400 MutexCounter();
00401 MutexCounter(int initial);
00402
00403 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00404 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00405 };
00406
00417 class CCXX_CLASS_EXPORT AtomicCounter
00418 {
00419 #ifndef WIN32
00420 private:
00421 #ifdef HAVE_ATOMIC
00422 atomic_t atomic;
00423 #else
00424 int counter;
00425 Mutex lock;
00426 #endif
00427
00428 public:
00432 AtomicCounter();
00433
00439 AtomicCounter(int value);
00440
00441 int operator++(void);
00442 int operator--(void);
00443 int operator+=(int change);
00444 int operator-=(int change);
00445 int operator+(int change);
00446 int operator-(int change);
00447 int operator=(int value);
00448 bool operator!(void);
00449 operator int();
00450 #else
00451 private:
00452 long atomic;
00453
00454 public:
00455 inline AtomicCounter()
00456 {atomic = 0;};
00457
00458 inline AtomicCounter(int value)
00459 {atomic = value;};
00460
00461 inline int operator++(void)
00462 {return InterlockedIncrement(&atomic);};
00463
00464 inline int operator--(void)
00465 {return InterlockedDecrement(&atomic);};
00466
00467 int operator+=(int change);
00468
00469 int operator-=(int change);
00470
00471 inline int operator+(int change)
00472 {return atomic + change;};
00473
00474 inline int operator-(int change)
00475 {return atomic - change;};
00476
00477 inline int operator=(int value)
00478 {return InterlockedExchange(&atomic, value);};
00479
00480 inline bool operator!(void)
00481 {return (atomic == 0) ? true : false;};
00482
00483 inline operator int()
00484 {return atomic;};
00485 #endif
00486 };
00487
00488
00489 #ifndef WIN32
00490
00500 class Conditional : public Mutex
00501 {
00502 private:
00503 pthread_cond_t _cond;
00504
00505 public:
00509 Conditional();
00510
00514 virtual ~Conditional();
00515
00521 void Signal(bool broadcast);
00522
00526 void Wait(timeout_t timer = 0);
00527 };
00528 #endif
00529
00547 class CCXX_CLASS_EXPORT Semaphore
00548 {
00549 private:
00550 #ifndef WIN32
00551 #ifdef CCXX_SYSV_SEMAPHORES
00552 int _semaphore;
00553 #else
00554 sem_t _semaphore;
00555 #endif
00556 #else // WIN32
00557 HANDLE semObject;
00558 #endif // !WIN32
00559
00560 public:
00569 Semaphore(size_t resource = 0);
00570
00577 virtual ~Semaphore();
00578
00592 void Wait(void);
00593
00605 bool TryWait(void);
00606
00618 void Post(void);
00619
00620
00626 #ifndef WIN32
00627 #ifndef __CYGWIN32__
00628 int getValue(void);
00629 #endif
00630 #endif
00631 };
00632
00646 class CCXX_CLASS_EXPORT Event
00647 {
00648 private:
00649 #ifndef WIN32
00650 Mutex mutex;
00651 pthread_cond_t _cond;
00652 bool _signaled;
00653 int _count;
00654 #else
00655 HANDLE cond;
00656 #endif
00657
00658 public:
00659 Event();
00660
00661 virtual ~Event();
00662
00669 void Reset(void);
00670
00674 void Signal(void);
00675
00684 bool Wait(timeout_t timer);
00685 bool Wait(void);
00686 };
00687
00709 class CCXX_CLASS_EXPORT Buffer
00710 {
00711 private:
00712 Mutex lock_head, lock_tail;
00713 Semaphore size_head, size_tail;
00714 size_t _size;
00715 size_t _used;
00716
00717 protected:
00723 virtual int OnPeek(void *buf) = 0;
00729 virtual int OnWait(void *buf) = 0;
00735 virtual int OnPost(void *buf) = 0;
00736
00737 public:
00742 Buffer(size_t capacity);
00747 virtual ~Buffer()
00748 {return;};
00749
00754 inline size_t getSize(void)
00755 {return _size;};
00756
00763 inline size_t getUsed(void)
00764 {return _used;};
00765
00774 int Wait(void *buf);
00775
00783 int Post(void *buf);
00784
00791 int Peek(void *buf);
00792
00797 virtual bool isValid(void)
00798 {return true;};
00799 };
00800
00808 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00809 {
00810 private:
00811 char *buf, *head, *tail;
00812 size_t objsize;
00813
00814 protected:
00820 int OnPeek(void *buf);
00821
00827 int OnWait(void *buf);
00828
00834 int OnPost(void *buf);
00835
00836 public:
00844 FixedBuffer(size_t capacity, size_t objsize);
00845
00852 FixedBuffer(const FixedBuffer &fb);
00853
00857 virtual ~FixedBuffer();
00858
00859 FixedBuffer &operator=(const FixedBuffer &fb);
00860
00861 bool isValid(void);
00862 };
00863
01011 class Thread
01012 {
01013 #ifndef WIN32
01014 friend class PosixThread;
01015 friend RETSIGTYPE ccxx_sigsuspend(int);
01016 #endif
01017 private:
01018 friend class Slog;
01019
01020 static Thread *_main;
01021
01022 Thread *_parent;
01023 #ifndef WIN32
01024 pthread_t _tid;
01025 pthread_attr_t _attr;
01026 AtomicCounter _suspendcount;
01027 #else
01028 DWORD _tid;
01029 HANDLE _cancellation;
01030 #endif
01031 thread_cancel_t _cancel;
01032 jmp_buf _env;
01033 Semaphore *_start;
01034 int _msgpos;
01035 char _msgbuf[128];
01036 throw_t _throw;
01037
01038 #ifndef WIN32
01039 friend void execHandler(Thread *th);
01040 friend Thread *getThread(void);
01041 #else
01042 bool _active:1;
01043 bool _suspendEnable:1;
01044 static unsigned __stdcall Execute(Thread *th);
01045 HANDLE _hThread;
01046 #endif
01047
01048 protected:
01058 virtual void Run(void) = 0;
01059
01072 CCXX_MEMBER_EXPORT(virtual void) Final(void)
01073 {return;};
01074
01085 CCXX_MEMBER_EXPORT(virtual void) Initial(void)
01086 {return;};
01087
01097 CCXX_MEMBER_EXPORT(virtual void*) getExtended(void)
01098 {return NULL;};
01099
01107 CCXX_MEMBER_EXPORT(virtual void) Notify(Thread *th)
01108 {return;};
01109
01119 CCXX_MEMBER_EXPORT(void) Sleep(timeout_t msec)
01120 #ifndef WIN32
01121 {ccxx_sleep(msec);}
01122 #endif
01123 ;
01124
01125
01131 inline void Exit(void)
01132 {longjmp(_env, 1);};
01133
01138 CCXX_MEMBER_EXPORT(void) Yield(void);
01139
01143 CCXX_MEMBER_EXPORT(void) testCancel(void);
01144
01153 CCXX_MEMBER_EXPORT(void) setCancel(thread_cancel_t mode);
01154
01162 CCXX_MEMBER_EXPORT(void) setSuspend(thread_suspend_t mode);
01163
01172 CCXX_MEMBER_EXPORT(void) Terminate(void);
01173
01177 inline void clrParent(void)
01178 {_parent = NULL;};
01179
01180 #ifdef WIN32
01181
01182 CCXX_MEMBER_EXPORT(DWORD) WaitHandle(HANDLE obj, timeout_t timeout);
01183 #endif
01184
01185 public:
01194 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(bool isMain);
01195
01208 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(int pri = 0, size_t stack = 0);
01209
01210
01211 #ifndef WIN32
01212
01219 Thread(const Thread &th);
01220 #endif
01221
01228 CCXX_MEMBER_EXPORT(virtual) ~Thread()
01229 {Terminate();};
01230
01243 CCXX_MEMBER_EXPORT(int) Start(Semaphore *start = 0);
01244
01253 CCXX_MEMBER_EXPORT(int) Detach(Semaphore *start = 0);
01254
01261 inline Thread *getParent(void)
01262 {return _parent;};
01263
01270 CCXX_MEMBER_EXPORT(void) Suspend(void);
01271
01275 CCXX_MEMBER_EXPORT(void) Resume(void);
01276
01283 inline thread_cancel_t getCancel(void)
01284 {return _cancel;};
01285
01292 bool isRunning(void)
01293 #ifdef WIN32
01294 {return (_tid != 0) ? true : false;}
01295 #endif
01296 ;
01297
01304 bool isThread(void)
01305 #ifdef WIN32
01306 {return ((_tid == GetCurrentThreadId())) ? true : false;}
01307 #endif
01308 ;
01309
01315 friend CCXX_EXPORT(throw_t) getException(void);
01316
01322 friend CCXX_EXPORT(void) setException(throw_t mode);
01323
01324
01331 friend inline void operator++(Thread &th)
01332 {th._start->Post();};
01333
01334 friend inline void operator--(Thread &th)
01335 {th._start->Wait();};
01336
01342 friend CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
01343
01347 friend CCXX_EXPORT(void) ccxx_yield(void);
01348
01349 #ifdef WIN32
01350
01351 inline bool isCancelled(void)
01352 {return waitThread(_cancellation, 0) == WAIT_OBJECT_0; };
01353
01354 inline bool isCancelled(timeout_t timer)
01355 {return waitThread(_cancellation, timer) == WAIT_OBJECT_0; };
01356
01357 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01358 #endif
01359 };
01360
01361 #ifndef WIN32
01362 extern "C" void sigHandler(int signo);
01363
01364 typedef int signo_t;
01365
01366 class PosixThread: public Thread
01367 {
01368 private:
01369 #ifndef WIN32
01370 friend void execHandler(Thread *th);
01371 #endif
01372 #ifndef CCXX_SIG_THREAD_ALARM
01373 static PosixThread *_timer;
01374 static Mutex _arm;
01375 #endif
01376
01377 time_t _alarm;
01378 friend void sigHandler(int signo);
01379 inline static void SignalThread(Thread* th,signo_t signo)
01380 {pthread_kill(th->_tid, signo);};
01381 protected:
01382
01389 inline void SignalParent(signo_t signo)
01390 { SignalThread(_parent,signo); };
01391
01398 inline void SignalMain(signo_t signo)
01399 { SignalThread(_main,signo);};
01400
01405 virtual void OnTimer(void)
01406 {return;};
01407
01412 virtual void OnHangup(void)
01413 {return;};
01414
01419 virtual void OnException(void)
01420 {return;};
01421
01426 virtual void OnDisconnect(void)
01427 {return;};
01428
01433 virtual void OnPolling(void)
01434 {return;};
01435
01442 virtual void OnSignal(int signo)
01443 {return;};
01444
01454 void setTimer(timeout_t timer);
01455
01462 timeout_t getTimer(void);
01463
01469 void endTimer(void);
01470
01477 void WaitSignal(signo_t signo);
01478
01485 void setSignal(int signo, bool mode);
01486 public:
01487
01493 inline void SignalThread(int signo)
01494 {SignalThread(this, signo);};
01495
01502 friend void siginstall(int signo);
01503 };
01504 #endif
01505
01520 class CCXX_CLASS_EXPORT ThreadKey
01521 {
01522 private:
01523 #ifndef WIN32
01524 pthread_key_t key;
01525 #else
01526 DWORD key;
01527 #endif
01528
01529 public:
01533 ThreadKey();
01537 virtual ~ThreadKey();
01545 void *getKey(void);
01553 void setKey(void *);
01554 };
01555
01566 class CCXX_CLASS_EXPORT TimerPort
01567 {
01568 #ifndef WIN32
01569 struct timeval timer;
01570 #else
01571 DWORD timer;
01572 #endif
01573 bool active;
01574
01575 public:
01582 TimerPort();
01583
01592 void setTimer(timeout_t timeout = 0);
01593
01603 void incTimer(timeout_t timeout);
01604
01610 void endTimer(void);
01611
01622 timeout_t getTimer(void);
01623
01632 timeout_t getElapsed(void);
01633 };
01634
01635 inline int get(Buffer &b, void *o)
01636 {return b.Wait(o);};
01637
01638 inline int put(Buffer &b, void *o)
01639 {return b.Post(o);};
01640
01641 inline int peek(Buffer &b, void *o)
01642 {return b.Peek(o);};
01643
01644
01645
01646 #ifndef WIN32
01647
01648
01649 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01650 void wait(signo_t signo);
01651
01660 void pdetach(void);
01661 #endif // !WIN32
01662
01663
01664 #ifndef WIN32
01665 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01666 #if defined(HAVE_SYS_STREAM_H)
01667 #if defined(__linux__)
01668 #define CCXX_USE_POLL 1
01669 #endif
01670 #else
01671 #define CCXX_USE_POLL 1
01672 #endif
01673 #endif
01674
01675 #ifdef CCXX_USE_POLL
01676
01684 class Poller
01685 {
01686 private:
01687 int nufds;
01688 pollfd *ufds;
01689
01690 public:
01691 Poller();
01692
01693 virtual ~Poller();
01694
01702 pollfd *getList(int cnt);
01703
01709 inline pollfd *getList(void)
01710 {return ufds;};
01711 };
01712 #endif
01713 #endif // !WIN32
01714
01715 #ifdef COMMON_STD_EXCEPTION
01716
01722 class ThrException : public Exception
01723 {
01724 public:
01725 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01726 };
01727
01734 class SyncException : public ThrException
01735 {
01736 public:
01737 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01738 };
01739 #endif
01740
01741 #ifdef CCXX_NAMESPACES
01742 };
01743 #endif
01744
01745 #endif
01746