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 WIN32
00058 #if (defined(__FreeBSD__) && __FreeBSD__ <= 3) || defined(_AIX)
00059 #define CCXX_SYSV_SEMAPHORES
00060 #endif
00061
00062 #ifdef MACOSX
00063 #define CCXX_NAMED_SEMAPHORES
00064 #define CCXX_BROKEN_SEMGETVALUE
00065 #endif
00066
00067 #ifndef HAVE_PTHREAD_H
00068 #include <pthread.h>
00069 #ifndef CCXX_SYSV_SEMAPHORES
00070 #include <semaphore.h>
00071 #endif
00072 #endif
00073 #endif // !WIN32
00074
00075 #undef CCXX_USE_WIN32_ATOMIC
00076 #ifndef WIN32
00077 #include <time.h>
00078 #include <signal.h>
00079 #include <unistd.h>
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
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #else // WIN32
00098 typedef DWORD cctid_t;
00099 typedef DWORD timeout_t;
00100
00101 #define MAX_SEM_VALUE 1000000
00102 #define CCXX_USE_WIN32_ATOMIC 1
00103 #if defined(__CYGWIN32__)
00104
00105 #else
00106 #if _MSC_VER < 1300
00107 __declspec(dllimport) long __stdcall InterlockedIncrement(long *);
00108 __declspec(dllimport) long __stdcall InterlockedDecrement(long *);
00109 __declspec(dllimport) long __stdcall InterlockedExchange(long *, long);
00110 #endif
00111 #endif
00112
00113 #endif // !WIN32
00114
00115 #ifdef CCXX_NAMESPACES
00116 namespace ost {
00117 #endif
00118
00119 class __EXPORT Thread;
00120 class __EXPORT ThreadKey;
00121
00122 #define TIMEOUT_INF ~((timeout_t) 0)
00123
00124 #define ENTER_CRITICAL enterMutex();
00125 #define LEAVE_CRITICAL leaveMutex();
00126 #define ENTER_DEFERRED setCancel(cancelDeferred);
00127 #define LEAVE_DEFERRED setCancel(cancelImmediate);
00128
00129 #ifndef WIN32
00130
00131
00132
00133
00134
00135
00136 #undef sleep
00137 #define psleep(x) (sleep)(x)
00138
00139 #endif // !WIN32
00140
00141 #undef Yield
00142
00143 class __EXPORT Conditional;
00144 class __EXPORT Event;
00145
00189 class __EXPORT Mutex
00190 {
00191 friend class Conditional;
00192 friend class Event;
00193 private:
00194 static bool _debug;
00195 const char *_name;
00196 #ifndef WIN32
00197 #ifndef PTHREAD_MUTEXTYPE_RECURSIVE
00198 volatile int _level;
00199 volatile Thread *_tid;
00200 #endif
00201
00202
00203
00204
00205
00206
00207
00208
00209 pthread_mutex_t _mutex;
00210 #else
00211 HANDLE mutex;
00212 #endif
00213
00214 public:
00218 Mutex(const char *name = NULL);
00219
00225 virtual ~Mutex();
00226
00232 static void setDebug(bool mode)
00233 {_debug = mode;};
00234
00242 void enterMutex(void);
00243
00254 bool tryEnterMutex(void);
00255
00266 void leaveMutex(void);
00267 };
00268
00292 class __EXPORT MutexLock
00293 {
00294 private:
00295 Mutex& mutex;
00296 public:
00300 MutexLock( Mutex& _mutex ) : mutex( _mutex )
00301 { mutex.enterMutex(); }
00305
00306 ~MutexLock()
00307 { mutex.leaveMutex(); }
00308 };
00309
00318 class __EXPORT ThreadLock
00319 {
00320 private:
00321 #ifdef HAVE_PTHREAD_RWLOCK
00322 pthread_rwlock_t _lock;
00323 #else
00324 Mutex mutex;
00325 #endif
00326
00327 public:
00331 ThreadLock();
00332
00336 virtual ~ThreadLock();
00337
00341 void readLock(void);
00342
00346 void writeLock(void);
00347
00353 bool tryReadLock(void);
00354
00360 bool tryWriteLock(void);
00361
00365 void unlock(void);
00366 };
00367
00377 class __EXPORT MutexCounter : public Mutex
00378 {
00379 private:
00380 int counter;
00381
00382 public:
00383 MutexCounter(const char *id = NULL);
00384 MutexCounter(int initial, const char *id = NULL);
00385
00386 friend __EXPORT int operator++(MutexCounter &mc);
00387 friend __EXPORT int operator--(MutexCounter &mc);
00388 };
00389
00400 class __EXPORT AtomicCounter
00401 {
00402 #ifndef CCXX_USE_WIN32_ATOMIC
00403 private:
00404 #ifdef HAVE_ATOMIC
00405 atomic_t atomic;
00406 #else
00407 int counter;
00408 Mutex lock;
00409 #endif
00410
00411 public:
00415 AtomicCounter();
00416
00422 AtomicCounter(int value);
00423
00424 int operator++(void);
00425 int operator--(void);
00426 int operator+=(int change);
00427 int operator-=(int change);
00428 int operator+(int change);
00429 int operator-(int change);
00430 int operator=(int value);
00431 bool operator!(void);
00432 operator int();
00433 #else
00434 private:
00435 long atomic;
00436
00437 public:
00438 inline AtomicCounter()
00439 {atomic = 0;};
00440
00441 inline AtomicCounter(int value)
00442 {atomic = value;};
00443
00444 inline int operator++(void)
00445 {return InterlockedIncrement(&atomic);};
00446
00447 inline int operator--(void)
00448 {return InterlockedDecrement(&atomic);};
00449
00450 int operator+=(int change);
00451
00452 int operator-=(int change);
00453
00454 inline int operator+(int change)
00455 {return atomic + change;};
00456
00457 inline int operator-(int change)
00458 {return atomic - change;};
00459
00460 inline int operator=(int value)
00461 {return InterlockedExchange(&atomic, value);};
00462
00463 inline bool operator!(void)
00464 {return (atomic == 0) ? true : false;};
00465
00466 inline operator int()
00467 {return atomic;};
00468 #endif
00469 };
00470
00471 #ifndef WIN32
00472
00492 class __EXPORT Conditional : public Mutex
00493 {
00494 private:
00495 pthread_cond_t _cond;
00496
00497 public:
00501 Conditional(const char *id = NULL);
00502
00506 virtual ~Conditional();
00507
00513 void signal(bool broadcast);
00514
00521 bool wait(timeout_t timer = 0, bool locked = false);
00522
00523 };
00524 #endif
00525
00543 class __EXPORT Semaphore
00544 {
00545 private:
00546 #ifndef WIN32
00547 #ifdef CCXX_SYSV_SEMAPHORES
00548 int _semaphore;
00549 #else
00550 sem_t _semaphore;
00551 sem_t *_semobject;
00552 #endif
00553 #else // WIN32
00554 HANDLE semObject;
00555 #endif // !WIN32
00556
00557 public:
00566 Semaphore(size_t resource = 0);
00567
00574 virtual ~Semaphore();
00575
00589 void wait(void);
00590
00602 bool tryWait(void);
00603
00615 void post(void);
00616
00617
00623 #ifndef WIN32
00624 #ifndef __CYGWIN32__
00625 int getValue(void);
00626 #endif
00627 #endif
00628 };
00629
00643 class __EXPORT Event
00644 {
00645 private:
00646 #ifndef WIN32
00647 Mutex mutex;
00648 pthread_cond_t _cond;
00649 bool _signaled;
00650 int _count;
00651 #else
00652 HANDLE cond;
00653 #endif
00654
00655 public:
00656 Event();
00657
00658 virtual ~Event();
00659
00666 void reset(void);
00667
00671 void signal(void);
00672
00681 bool wait(timeout_t timer);
00682 bool wait(void);
00683 };
00684
00685
00867 class __EXPORT Thread
00868 {
00869 public:
00873 typedef enum Throw {
00874 throwNothing,
00875 throwObject,
00876 throwException
00877 } Throw;
00878
00882 typedef enum Cancel
00883 {
00884 cancelInitial=0,
00885 cancelDeferred=1,
00886 cancelImmediate,
00887 cancelDisabled,
00888 cancelManual,
00890 cancelDefault=cancelDeferred
00892 } Cancel;
00893
00897 typedef enum Suspend
00898 {
00899 suspendEnable,
00900 suspendDisable
00901 } Suspend;
00902
00903 #ifndef WIN32
00904
00905 friend class PosixThread;
00906 #endif
00907
00908 friend class DummyThread;
00909 private:
00910 friend class postream_type;
00911 friend class Slog;
00912
00913 Semaphore joinSem;
00914 static Thread* _main;
00915
00916 Thread *_parent;
00917 enum Cancel _cancel;
00918 Semaphore *_start;
00919
00920
00921 friend class ThreadImpl;
00922 class ThreadImpl* priv;
00923
00924 public:
00925 static Thread *getThread(void);
00926 friend inline Thread *getThread() {return Thread::getThread();};
00927
00928 private:
00929 #ifdef WIN32
00930 static unsigned __stdcall Execute(Thread *th);
00931 #endif
00932
00933
00934 void close();
00935
00936 private:
00937 char _name[32];
00938 static size_t _autostack;
00939
00940 #ifdef WIN32
00941 DWORD waitHandle(HANDLE obj, timeout_t timeout);
00942 #endif
00943
00944 protected:
00952 void setName(const char *text);
00953
00963 virtual void run(void) = 0;
00964
00986 virtual void final(void)
00987 {return;};
00988
01000 virtual void initial(void)
01001 {return;};
01002
01012 virtual void* getExtended(void)
01013 {return NULL;};
01014
01022 virtual void notify(Thread*)
01023 {return;};
01024
01030 void exit(void);
01031
01035 bool testCancel(void);
01036
01046 void setCancel(Cancel mode);
01047
01055 void setSuspend(Suspend mode);
01056
01065 void terminate(void);
01066
01070 inline void clrParent(void)
01071 {_parent = NULL;};
01072
01073 public:
01082 Thread(bool isMain);
01083
01095 Thread(int pri = 0, size_t stack = 0);
01096
01097 #ifndef WIN32
01098
01106 Thread(const Thread &th);
01107 #endif
01108
01115 virtual ~Thread();
01116
01122 static void setStack(size_t size = 0)
01123 {_autostack = size;};
01124
01134 static void sleep(timeout_t msec);
01135
01140 static void yield(void);
01141
01154 int start(Semaphore *start = 0);
01155
01164 int detach(Semaphore *start = 0);
01165
01172 inline Thread *getParent(void)
01173 {return _parent;};
01174
01181 void suspend(void);
01182
01186 void resume(void);
01187
01194 inline Cancel getCancel(void)
01195 {return _cancel;};
01196
01203 bool isRunning(void);
01204
01210 bool isDetached(void);
01211
01215 void join(void);
01216
01223 bool isThread(void);
01224
01230 cctid_t getThreadId(void) const;
01231
01238 const char *getThreadName(void)
01239 {return _name;};
01240
01246 static Throw getException(void);
01247
01253 static void setException(Throw mode);
01254
01261 friend inline void operator++(Thread &th)
01262 {if (th._start) th._start->post();};
01263
01264 friend inline void operator--(Thread &th)
01265 {if (th._start) th._start->wait();};
01266
01267 #ifdef WIN32
01268 bool isCancelled();
01269
01270 static DWORD waitThread(HANDLE hRef, timeout_t timeout);
01271 #endif
01272 };
01273
01274 #if !defined(WIN32) && !defined(__MINGW32__)
01275 typedef int signo_t;
01276
01277 class PosixThread: public Thread
01278 {
01279 private:
01280 #ifndef WIN32
01281
01282 friend class ThreadImpl;
01283 friend class Thread;
01284 #endif
01285 #ifndef CCXX_SIG_THREAD_ALARM
01286 static PosixThread *_timer;
01287 static Mutex _arm;
01288 #endif
01289
01290 time_t _alarm;
01291 static void signalThread(Thread* th,signo_t signo);
01292 protected:
01293
01300 inline void signalParent(signo_t signo)
01301 { signalThread(_parent,signo); };
01302
01309 inline void signalMain(signo_t signo)
01310 { signalThread(_main,signo);};
01311
01316 virtual void onTimer(void)
01317 {return;};
01318
01323 virtual void onHangup(void)
01324 {return;};
01325
01330 virtual void onException(void)
01331 {return;};
01332
01337 virtual void onDisconnect(void)
01338 {return;};
01339
01344 virtual void onPolling(void)
01345 {return;};
01346
01353 virtual void onSignal(int)
01354 {return;};
01355
01368 void setTimer(timeout_t timer, bool periodic = false);
01369
01376 timeout_t getTimer(void) const;
01377
01383 void endTimer(void);
01384
01391 void waitSignal(signo_t signo);
01392
01399 void setSignal(int signo, bool active);
01400 public:
01401
01402 PosixThread(int pri = 0, size_t stack = 0);
01403
01409 inline void signalThread(int signo)
01410 {signalThread(this, signo);};
01411
01418 static void sigInstall(int signo);
01419 };
01420 #endif
01421
01436 class __EXPORT ThreadKey
01437 {
01438 private:
01439 #ifndef WIN32
01440 pthread_key_t key;
01441 typedef void (*TDestruct)(void*);
01442 friend class ThreadImpl;
01443 ThreadKey(TDestruct destruct);
01444 #else
01445 DWORD key;
01446 #endif
01447
01448 public:
01452 ThreadKey();
01456 virtual ~ThreadKey();
01464 void *getKey(void);
01472 void setKey(void *);
01473 };
01474
01485 class __EXPORT TimerPort
01486 {
01487 #ifndef WIN32
01488 struct timeval timer;
01489 #else
01490 DWORD timer;
01491 #endif
01492 bool active;
01493
01494 public:
01501 TimerPort();
01502
01511 void setTimer(timeout_t timeout = 0);
01512
01522 void incTimer(timeout_t timeout);
01523
01529 void endTimer(void);
01530
01542 timeout_t getTimer(void) const;
01543
01553 timeout_t getElapsed(void) const;
01554 };
01555
01556
01557
01558
01559 #if !defined(WIN32)
01560
01561
01562 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
01563
01564 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
01565 void wait(signo_t signo);
01566 #endif
01567
01568 #endif // !WIN32
01569
01570 #ifdef USE_POLL
01571
01579 class Poller
01580 {
01581 private:
01582 int nufds;
01583 pollfd *ufds;
01584
01585 public:
01586 Poller();
01587
01588 virtual ~Poller();
01589
01597 pollfd *getList(int cnt);
01598
01604 inline pollfd *getList(void)
01605 {return ufds;};
01606 };
01607 #endif
01608
01609 #ifdef CCXX_NAMESPACES
01610 };
01611 #endif
01612
01613 #endif
01614