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) || defined(_AIX)
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
00079 #define CCXX_SIG_THREAD_STOPCONT
00080 #endif
00081
00082 #ifdef _THR_UNIXWARE
00083 #undef PTHREAD_MUTEXTYPE_RECURSIVE
00084 #endif
00085
00086 typedef pthread_t cctid_t;
00087 typedef unsigned long timeout_t;
00088 #else // WIN32
00089 typedef DWORD cctid_t;
00090 typedef DWORD timeout_t;
00091
00092 #define MAX_SEM_VALUE 1000000
00093 #if defined(__CYGWIN32__)
00094 #include <Windows32/CommonFunctions.h>
00095 #else
00096 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00097 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00098 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00099 #endif
00100
00101 #endif // !WIN32
00102
00103 #ifdef CCXX_NAMESPACES
00104 namespace ost {
00105 #endif
00106
00107 enum throw_t {
00108 THROW_NOTHING,
00109 THROW_OBJECT,
00110 THROW_EXCEPTION
00111 };
00112 typedef enum throw_t throw_t;
00113 class Thread;
00114
00115 #define TIMEOUT_INF ~((timeout_t) 0)
00116
00117 #define ENTER_CRITICAL EnterMutex();
00118 #define LEAVE_CRITICAL LeaveMutex();
00119 #define ENTER_DEFERRED setCancel(THREAD_CANCEL_DEFERRED);
00120 #define LEAVE_DEFERRED setCancel(THREAD_CANCEL_IMMEDIATE);
00121
00122 enum thread_cancel_t
00123 {
00124 THREAD_CANCEL_INITIAL=0,
00125 THREAD_CANCEL_DEFERRED=1,
00126 THREAD_CANCEL_IMMEDIATE,
00127 THREAD_CANCEL_DISABLED,
00128 THREAD_CANCEL_MANUAL,
00129 THREAD_CANCEL_DEFAULT=THREAD_CANCEL_DEFERRED
00130 };
00131 typedef enum thread_cancel_t thread_cancel_t;
00132
00133 enum thread_suspend_t
00134 {
00135 THREAD_SUSPEND_ENABLE,
00136 THREAD_SUSPEND_DISABLE
00137 };
00138 typedef enum thread_suspend_t thread_suspend_t;
00139
00140 #ifndef WIN32
00141
00142
00143
00144
00145
00146
00147 #undef sleep
00148 #define psleep(x) (sleep)(x)
00149
00150 #ifndef CCXX_SIG_THREAD_STOPCONT
00151 #ifndef _THR_SUNOS5
00152 #ifndef HAVE_PTHREAD_SUSPEND
00153 static RETSIGTYPE ccxx_sigsuspend(int);
00154 #endif
00155 #endif
00156 #endif
00157 extern "C" void ccxx_exec_handler(Thread *th);
00158 extern "C" void ccxx_thread_cleanup(void* arg);
00159
00160 #endif // !WIN32
00161
00162
00163 CCXX_EXPORT(Thread*) getThread(void);
00164 CCXX_EXPORT(throw_t) getException(void);
00165 CCXX_EXPORT(void) setException(throw_t mode);
00166 CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
00167 CCXX_EXPORT(void) ccxx_yield(void);
00168
00169 #undef Yield
00170 #define sleep(x) ccxx_sleep((x) * 1000)
00171 #define yield() ccxx_yield()
00172
00173 #ifdef WIN32
00174 CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
00175 #endif
00176
00177 class Conditional;
00178 class CCXX_CLASS_EXPORT Event;
00179
00223 class CCXX_CLASS_EXPORT Mutex
00224 {
00225 friend class Conditional;
00226 friend class Event;
00227 private:
00228 #ifndef WIN32
00229 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00230 volatile int _level;
00231 volatile Thread *_tid;
00232 #endif
00233
00241 pthread_mutex_t _mutex;
00242 #else
00243 HANDLE mutex;
00244 #endif
00245
00246 public:
00250 Mutex();
00251
00257 virtual ~Mutex();
00258
00266 void EnterMutex(void);
00267
00278 bool TryEnterMutex(void);
00279
00290 void LeaveMutex(void);
00291 };
00292
00314 class MutexLock
00315 {
00316 private:
00317 Mutex& mutex;
00318 public:
00322 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00323 { mutex.EnterMutex(); }
00327
00328 ~MutexLock()
00329 { mutex.LeaveMutex(); }
00330 };
00331
00340 class CCXX_CLASS_EXPORT ThreadLock
00341 {
00342 private:
00343 #ifdef HAVE_PTHREAD_RWLOCK
00344 pthread_rwlock_t _lock;
00345 #else
00346 Mutex mutex;
00347 #endif
00348
00349 public:
00353 ThreadLock();
00354
00358 virtual ~ThreadLock();
00359
00363 void ReadLock(void);
00364
00368 void WriteLock(void);
00369
00375 bool TryReadLock(void);
00376
00382 bool TryWriteLock(void);
00383
00387 void Unlock(void);
00388 };
00389
00399 class CCXX_CLASS_EXPORT MutexCounter : public Mutex
00400 {
00401 private:
00402 int counter;
00403
00404 public:
00405 MutexCounter();
00406 MutexCounter(int initial);
00407
00408 friend CCXX_EXPORT(int) operator++(MutexCounter &mc);
00409 friend CCXX_EXPORT(int) operator--(MutexCounter &mc);
00410 };
00411
00422 class CCXX_CLASS_EXPORT AtomicCounter
00423 {
00424 #ifndef WIN32
00425 private:
00426 #ifdef HAVE_ATOMIC
00427 atomic_t atomic;
00428 #else
00429 int counter;
00430 Mutex lock;
00431 #endif
00432
00433 public:
00437 AtomicCounter();
00438
00444 AtomicCounter(int value);
00445
00446 int operator++(void);
00447 int operator--(void);
00448 int operator+=(int change);
00449 int operator-=(int change);
00450 int operator+(int change);
00451 int operator-(int change);
00452 int operator=(int value);
00453 bool operator!(void);
00454 operator int();
00455 #else
00456 private:
00457 long atomic;
00458
00459 public:
00460 inline AtomicCounter()
00461 {atomic = 0;};
00462
00463 inline AtomicCounter(int value)
00464 {atomic = value;};
00465
00466 inline int operator++(void)
00467 {return InterlockedIncrement(&atomic);};
00468
00469 inline int operator--(void)
00470 {return InterlockedDecrement(&atomic);};
00471
00472 int operator+=(int change);
00473
00474 int operator-=(int change);
00475
00476 inline int operator+(int change)
00477 {return atomic + change;};
00478
00479 inline int operator-(int change)
00480 {return atomic - change;};
00481
00482 inline int operator=(int value)
00483 {return InterlockedExchange(&atomic, value);};
00484
00485 inline bool operator!(void)
00486 {return (atomic == 0) ? true : false;};
00487
00488 inline operator int()
00489 {return atomic;};
00490 #endif
00491 };
00492
00493
00494 #ifndef WIN32
00495
00505 class Conditional : public Mutex
00506 {
00507 private:
00508 pthread_cond_t _cond;
00509
00510 public:
00514 Conditional();
00515
00519 virtual ~Conditional();
00520
00526 void Signal(bool broadcast);
00527
00531 void Wait(timeout_t timer = 0);
00532 };
00533 #endif
00534
00552 class CCXX_CLASS_EXPORT Semaphore
00553 {
00554 private:
00555 #ifndef WIN32
00556 #ifdef CCXX_SYSV_SEMAPHORES
00557 int _semaphore;
00558 #else
00559 sem_t _semaphore;
00560 #endif
00561 #else // WIN32
00562 HANDLE semObject;
00563 #endif // !WIN32
00564
00565 public:
00574 Semaphore(size_t resource = 0);
00575
00582 virtual ~Semaphore();
00583
00597 void Wait(void);
00598
00610 bool TryWait(void);
00611
00623 void Post(void);
00624
00625
00631 #ifndef WIN32
00632 #ifndef __CYGWIN32__
00633 int getValue(void);
00634 #endif
00635 #endif
00636 };
00637
00651 class CCXX_CLASS_EXPORT Event
00652 {
00653 private:
00654 #ifndef WIN32
00655 Mutex mutex;
00656 pthread_cond_t _cond;
00657 bool _signaled;
00658 int _count;
00659 #else
00660 HANDLE cond;
00661 #endif
00662
00663 public:
00664 Event();
00665
00666 virtual ~Event();
00667
00674 void Reset(void);
00675
00679 void Signal(void);
00680
00689 bool Wait(timeout_t timer);
00690 bool Wait(void);
00691 };
00692
00714 class CCXX_CLASS_EXPORT Buffer
00715 {
00716 private:
00717 Mutex lock_head, lock_tail;
00718 Semaphore size_head, size_tail;
00719 size_t _size;
00720 size_t _used;
00721
00722 protected:
00728 virtual int OnPeek(void *buf) = 0;
00734 virtual int OnWait(void *buf) = 0;
00740 virtual int OnPost(void *buf) = 0;
00741
00742 public:
00747 Buffer(size_t capacity);
00752 virtual ~Buffer()
00753 {return;};
00754
00759 inline size_t getSize(void)
00760 {return _size;};
00761
00768 inline size_t getUsed(void)
00769 {return _used;};
00770
00779 int Wait(void *buf);
00780
00788 int Post(void *buf);
00789
00796 int Peek(void *buf);
00797
00802 virtual bool isValid(void)
00803 {return true;};
00804 };
00805
00813 class CCXX_CLASS_EXPORT FixedBuffer : public Buffer
00814 {
00815 private:
00816 char *buf, *head, *tail;
00817 size_t objsize;
00818
00819 protected:
00825 int OnPeek(void *buf);
00826
00832 int OnWait(void *buf);
00833
00839 int OnPost(void *buf);
00840
00841 public:
00849 FixedBuffer(size_t capacity, size_t objsize);
00850
00857 FixedBuffer(const FixedBuffer &fb);
00858
00862 virtual ~FixedBuffer();
00863
00864 FixedBuffer &operator=(const FixedBuffer &fb);
00865
00866 bool isValid(void);
00867 };
00868
01016 class Thread
01017 {
01018 #ifndef WIN32
01019 friend class PosixThread;
01020 friend RETSIGTYPE ccxx_sigsuspend(int);
01021 friend void ccxx_exec_handler(Thread *th);
01022 friend void ccxx_thread_cleanup(void* arg);
01023 #endif
01024 private:
01025 friend class Slog;
01026
01027 static Thread *_main;
01028
01029 Thread *_parent;
01030 #ifndef WIN32
01031 pthread_t _tid;
01032 pthread_attr_t _attr;
01033 AtomicCounter _suspendcount;
01034 #else
01035 DWORD _tid;
01036 HANDLE _cancellation;
01037 #endif
01038 thread_cancel_t _cancel;
01039
01040 Semaphore *_start;
01041
01042
01043 int _msgpos;
01044 char _msgbuf[128];
01045 throw_t _throw;
01046
01047 #ifndef WIN32
01048 friend Thread *getThread(void);
01049 volatile bool _suspendEnable:1;
01050 unsigned int _type:2;
01051 #else
01052 bool _active:1;
01053 bool _suspendEnable:1;
01054 static unsigned __stdcall Execute(Thread *th);
01055 HANDLE _hThread;
01056 #endif
01057
01058 void Close();
01059
01060 protected:
01070 virtual void Run(void) = 0;
01071
01088 CCXX_MEMBER_EXPORT(virtual void) Final(void)
01089 {return;};
01090
01102 CCXX_MEMBER_EXPORT(virtual void) Initial(void)
01103 {return;};
01104
01114 CCXX_MEMBER_EXPORT(virtual void*) getExtended(void)
01115 {return NULL;};
01116
01124 CCXX_MEMBER_EXPORT(virtual void) Notify(Thread *th)
01125 {return;};
01126
01136 CCXX_MEMBER_EXPORT(void) Sleep(timeout_t msec)
01137 #ifndef WIN32
01138 {ccxx_sleep(msec);}
01139 #endif
01140 ;
01141
01147 CCXX_MEMBER_EXPORT(void) Exit(void);
01148
01153 CCXX_MEMBER_EXPORT(void) Yield(void);
01154
01158 CCXX_MEMBER_EXPORT(bool) testCancel(void);
01159
01169 CCXX_MEMBER_EXPORT(void) setCancel(thread_cancel_t mode);
01170
01178 CCXX_MEMBER_EXPORT(void) setSuspend(thread_suspend_t mode);
01179
01188 CCXX_MEMBER_EXPORT(void) Terminate(void);
01189
01193 inline void clrParent(void)
01194 {_parent = NULL;};
01195
01196 #ifdef WIN32
01197
01198 CCXX_MEMBER_EXPORT(DWORD) WaitHandle(HANDLE obj, timeout_t timeout);
01199 #endif
01200
01201 public:
01210 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(bool isMain);
01211
01224 CCXX_MEMBER_EXPORT(CCXX_EMPTY) Thread(int pri = 0, size_t stack = 0);
01225
01226
01227 #ifndef WIN32
01228
01235 Thread(const Thread &th);
01236 #endif
01237
01244 CCXX_MEMBER_EXPORT(virtual) ~Thread();
01245
01258 CCXX_MEMBER_EXPORT(int) Start(Semaphore *start = 0);
01259
01268 CCXX_MEMBER_EXPORT(int) Detach(Semaphore *start = 0);
01269
01276 inline Thread *getParent(void)
01277 {return _parent;};
01278
01285 CCXX_MEMBER_EXPORT(void) Suspend(void);
01286
01290 CCXX_MEMBER_EXPORT(void) Resume(void);
01291
01298 inline thread_cancel_t getCancel(void)
01299 {return _cancel;};
01300
01307 bool isRunning(void)
01308 #ifdef WIN32
01309 {return (_tid != 0) ? true : false;}
01310 #endif
01311 ;
01312
01319 bool isThread(void)
01320 #ifdef WIN32
01321 {return ((_tid == GetCurrentThreadId())) ? true : false;}
01322 #endif
01323 ;
01324
01330 friend CCXX_EXPORT(throw_t) getException(void);
01331
01337 friend CCXX_EXPORT(void) setException(throw_t mode);
01338
01339
01346 friend inline void operator++(Thread &th)
01347 {th._start->Post();};
01348
01349 friend inline void operator--(Thread &th)
01350 {th._start->Wait();};
01351
01357 friend CCXX_EXPORT(void) ccxx_sleep(timeout_t msec);
01358
01362 friend CCXX_EXPORT(void) ccxx_yield(void);
01363
01364 #ifdef WIN32
01365
01366 inline bool isCancelled(void)
01367 {return waitThread(_cancellation, 0) == WAIT_OBJECT_0; };
01368
01369 inline bool isCancelled(timeout_t timer)
01370 {return waitThread(_cancellation, timer) == WAIT_OBJECT_0; };
01371
01372 friend CCXX_EXPORT(DWORD) waitThread(HANDLE hRef, timeout_t timeout);
01373 #endif
01374 };
01375
01376 #if !defined(WIN32) && !defined(__CYGWIN32__) && !defined(__MINGW32__)
01377 extern "C" void sigHandler(int signo);
01378
01379 typedef int signo_t;
01380
01381 class PosixThread: public Thread
01382 {
01383 private:
01384 #ifndef WIN32
01385 friend void ccxx_exec_handler(Thread *th);
01386 friend class Thread;
01387 #endif
01388 #ifndef CCXX_SIG_THREAD_ALARM
01389 static PosixThread *_timer;
01390 static Mutex _arm;
01391 #endif
01392
01393 time_t _alarm;
01394 friend void sigHandler(int signo);
01395 inline static void SignalThread(Thread* th,signo_t signo)
01396 {pthread_kill(th->_tid, signo);};
01397 protected:
01398
01405 inline void SignalParent(signo_t signo)
01406 { SignalThread(_parent,signo); };
01407
01414 inline void SignalMain(signo_t signo)
01415 { SignalThread(_main,signo);};
01416
01421 virtual void OnTimer(void)
01422 {return;};
01423
01428 virtual void OnHangup(void)
01429 {return;};
01430
01435 virtual void OnException(void)
01436 {return;};
01437
01442 virtual void OnDisconnect(void)
01443 {return;};
01444
01449 virtual void OnPolling(void)
01450 {return;};
01451
01458 virtual void OnSignal(int signo)
01459 {return;};
01460
01470 void setTimer(timeout_t timer);
01471
01478 timeout_t getTimer(void);
01479
01485 void endTimer(void);
01486
01493 void WaitSignal(signo_t signo);
01494
01501 void setSignal(int signo, bool mode);
01502 public:
01503
01509 inline void SignalThread(int signo)
01510 {SignalThread(this, signo);};
01511
01518 friend void siginstall(int signo);
01519 };
01520 #endif
01521
01536 class CCXX_CLASS_EXPORT ThreadKey
01537 {
01538 private:
01539 #ifndef WIN32
01540 pthread_key_t key;
01541 #else
01542 DWORD key;
01543 #endif
01544
01545 public:
01549 ThreadKey();
01553 virtual ~ThreadKey();
01561 void *getKey(void);
01569 void setKey(void *);
01570 };
01571
01582 class CCXX_CLASS_EXPORT TimerPort
01583 {
01584 #ifndef WIN32
01585 struct timeval timer;
01586 #else
01587 DWORD timer;
01588 #endif
01589 bool active;
01590
01591 public:
01598 TimerPort();
01599
01608 void setTimer(timeout_t timeout = 0);
01609
01619 void incTimer(timeout_t timeout);
01620
01626 void endTimer(void);
01627
01638 timeout_t getTimer(void);
01639
01648 timeout_t getElapsed(void);
01649 };
01650
01651 inline int get(Buffer &b, void *o)
01652 {return b.Wait(o);};
01653
01654 inline int put(Buffer &b, void *o)
01655 {return b.Post(o);};
01656
01657 inline int peek(Buffer &b, void *o)
01658 {return b.Peek(o);};
01659
01660
01661
01662 #if !defined(WIN32)
01663
01664
01665 struct timespec *gettimeout(struct timespec *spec, timeout_t timeout);
01666
01667 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01668 void wait(signo_t signo);
01669 #endif
01670
01679 void pdetach(void);
01680 #endif // !WIN32
01681
01682
01683 #ifndef WIN32
01684 #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)
01685 #if defined(HAVE_SYS_STREAM_H)
01686 #if defined(__linux__)
01687 #define CCXX_USE_POLL 1
01688 #endif
01689 #else
01690 #define CCXX_USE_POLL 1
01691 #endif
01692 #endif
01693
01694 #ifdef CCXX_USE_POLL
01695
01703 class Poller
01704 {
01705 private:
01706 int nufds;
01707 pollfd *ufds;
01708
01709 public:
01710 Poller();
01711
01712 virtual ~Poller();
01713
01721 pollfd *getList(int cnt);
01722
01728 inline pollfd *getList(void)
01729 {return ufds;};
01730 };
01731 #endif
01732 #endif // !WIN32
01733
01734 #ifdef COMMON_STD_EXCEPTION
01735
01741 class ThrException : public Exception
01742 {
01743 public:
01744 ThrException(const std::string &what_arg) : Exception(what_arg) {};
01745 };
01746
01753 class SyncException : public ThrException
01754 {
01755 public:
01756 SyncException(const std::string &what_arg) : ThrException(what_arg) {};
01757 };
01758 #endif
01759
01760 #ifdef CCXX_NAMESPACES
01761 };
01762 #endif
01763
01764 #endif
01765