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 #ifndef _PTHREAD
00035 #define _PTHREAD
00036
00037 #ifdef P_USE_PRAGMA
00038 #pragma interface
00039 #endif
00040
00041 #ifdef Priority
00042 #undef Priority
00043 #endif
00044
00045 #include <ptlib/mutex.h>
00046
00047 class PSemaphore;
00048
00049 #define PThreadIdentifer PThreadIdentifier
00050
00051 typedef P_THREADIDENTIFIER PThreadIdentifier;
00052
00054
00055
00069 class PThread : public PObject
00070 {
00071 PCLASSINFO(PThread, PObject);
00072
00073 public:
00076
00077 enum Priority {
00078 LowestPriority,
00079
00080 LowPriority,
00081
00082 NormalPriority,
00083
00084 HighPriority,
00085
00086 HighestPriority,
00087
00088 NumPriorities
00089 };
00090
00092 enum AutoDeleteFlag {
00094 AutoDeleteThread,
00095
00097 NoAutoDeleteThread
00098 };
00099
00122 PThread(
00123 PINDEX,
00124 AutoDeleteFlag deletion = AutoDeleteThread,
00126 Priority priorityLevel = NormalPriority,
00127 const PString & threadName = PString::Empty()
00128 );
00129
00137 ~PThread();
00139
00146 void PrintOn(
00147 ostream & strm
00148 ) const;
00150
00158 virtual void Restart();
00159
00171 virtual void Terminate();
00172
00178 virtual PBoolean IsTerminated() const;
00179
00185 void WaitForTermination() const;
00186 PBoolean WaitForTermination(
00187 const PTimeInterval & maxWait
00188 ) const;
00189
00202 virtual void Suspend(
00203 PBoolean susp = PTrue
00204 );
00205
00225 virtual void Resume();
00226
00234 virtual PBoolean IsSuspended() const;
00235
00237 static void Sleep(
00238 const PTimeInterval & delay
00239 );
00240
00244 virtual void SetPriority(
00245 Priority priorityLevel
00246 );
00247
00253 virtual Priority GetPriority() const;
00254
00258 virtual void SetAutoDelete(
00259 AutoDeleteFlag deletion = AutoDeleteThread
00260 );
00261
00265 void SetNoAutoDelete() { SetAutoDelete(NoAutoDeleteThread); }
00266
00272 virtual PString GetThreadName() const;
00273
00279 virtual void SetThreadName(
00280 const PString & name
00281 );
00283
00291 virtual PThreadIdentifier GetThreadId() const;
00292 static PThreadIdentifier GetCurrentThreadId();
00293
00301 virtual void Main() = 0;
00302
00312 static PThread * Current();
00313
00320 static void Yield();
00321
00326 static PThread * Create(
00327 const PNotifier & notifier,
00328 INT parameter = 0,
00329 AutoDeleteFlag deletion = AutoDeleteThread,
00331 Priority priorityLevel = NormalPriority,
00332 const PString & threadName = PString::Empty(),
00333 PINDEX stackSize = 65536
00334 );
00335 static PThread * Create(
00336 const PNotifier & notifier,
00337 const PString & threadName
00338 ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00340
00341 protected:
00342 void InitialiseProcessThread();
00343
00344
00345
00346
00347 private:
00348 PThread();
00349
00350
00351 friend class PProcess;
00352
00353
00354 PThread(const PThread &) : PObject () { }
00355
00356
00357 PThread & operator=(const PThread &) { return *this; }
00358
00359
00360 PBoolean autoDelete;
00361
00362
00363
00364 PString threadName;
00365 PMutex threadNameMutex;
00366
00367 #if PTRACING
00368 public:
00369 struct TraceInfo {
00370 TraceInfo()
00371 { traceBlockIndentLevel = 0; }
00372
00373 PStack<PStringStream> traceStreams;
00374 unsigned traceLevel;
00375 unsigned traceBlockIndentLevel;
00376 };
00377
00378 #ifndef P_HAS_THREADLOCAL_STORAGE
00379 private:
00380 friend class PTrace;
00381 TraceInfo traceInfo;
00382 #endif // P_HAS_THREADLOCAL_STORAGE
00383 #endif // PTRACING
00384
00385
00386 #ifdef _WIN32
00387 #include "msos/ptlib/thread.h"
00388 #else
00389 #include "unix/ptlib/thread.h"
00390 #endif
00391 };
00392
00393
00394 #if defined(_WIN32) && !defined(_WIN32_WCE)
00395 #define PTHREAD_ID_FMT ":%u"
00396 #else
00397 #define PTHREAD_ID_FMT ":0x%x"
00398 #endif
00399
00400 #ifdef _MSC_VER
00401 #pragma warning(disable:4355)
00402 #endif
00403
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 class PThreadMain : public PThread
00421 {
00422 PCLASSINFO(PThreadMain, PThread);
00423 public:
00424 typedef void (*FnType)();
00425 PThreadMain(FnType _fn, PBoolean _autoDelete = PFalse)
00426 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn)
00427 { PThread::Resume(); }
00428 PThreadMain(const char * _file, int _line, FnType _fn, PBoolean _autoDelete = PFalse)
00429 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00430 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn)
00431 { PThread::Resume(); }
00432 virtual void Main()
00433 { (*fn)(); }
00434 FnType fn;
00435 };
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 template<typename Arg1Type>
00450 class PThread1Arg : public PThread
00451 {
00452 PCLASSINFO(PThread1Arg, PThread);
00453 public:
00454 typedef void (*FnType)(Arg1Type arg1);
00455 PThread1Arg(Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00456 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00457 arg1(_arg1)
00458 { PThread::Resume(); }
00459 PThread1Arg(const char * _file, int _line, Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00460 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00461 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00462 arg1(_arg1)
00463 { PThread::Resume(); }
00464 virtual void Main()
00465 { (*fn)(arg1); }
00466 FnType fn;
00467 Arg1Type arg1;
00468 };
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483 template<typename Arg1Type, typename Arg2Type>
00484 class PThread2Arg : public PThread
00485 {
00486 PCLASSINFO(PThread2Arg, PThread);
00487 public:
00488 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
00489 PThread2Arg(Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00490 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00491 arg1(_arg1), arg2(_arg2)
00492 { PThread::Resume(); }
00493 PThread2Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00494 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00495 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00496 arg1(_arg1), arg2(_arg2)
00497 { PThread::Resume(); }
00498 virtual void Main()
00499 { (*fn)(arg1, arg2); }
00500 FnType fn;
00501 Arg1Type arg1;
00502 Arg2Type arg2;
00503 };
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00518 class PThread3Arg : public PThread
00519 {
00520 PCLASSINFO(PThread3Arg, PThread);
00521 public:
00522 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
00523 PThread3Arg(Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00524 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00525 arg1(_arg1), arg2(_arg2), arg3(_arg3)
00526 { PThread::Resume(); }
00527 PThread3Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00528 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00529 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00530 arg1(_arg1), arg2(_arg2), arg3(_arg3)
00531 { PThread::Resume(); }
00532 virtual void Main()
00533 { (*fn)(arg1, arg2, arg3); }
00534 FnType fn;
00535 Arg1Type arg1;
00536 Arg2Type arg2;
00537 Arg2Type arg3;
00538 };
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 template <typename ObjType>
00557 class PThreadObj : public PThread
00558 {
00559 public:
00560 PCLASSINFO(PThreadObj, PThread);
00561 public:
00562 typedef void (ObjType::*ObjTypeFn)();
00563 PThreadObj(ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00564 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00565 obj(_obj), fn(_fn)
00566 { PThread::Resume(); }
00567 PThreadObj(const char * _file, int _line, ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00568 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00569 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00570 obj(_obj), fn(_fn)
00571 { PThread::Resume(); }
00572 void Main()
00573 { (obj.*fn)(); }
00574
00575 protected:
00576 ObjType & obj;
00577 ObjTypeFn fn;
00578 };
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 template <class ObjType, typename Arg1Type>
00598 class PThreadObj1Arg : public PThread
00599 {
00600 PCLASSINFO(PThreadObj1Arg, PThread);
00601 public:
00602 typedef void (ObjType::*ObjTypeFn)(Arg1Type);
00603 PThreadObj1Arg(ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00604 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00605 obj(_obj), fn(_fn), arg1(_arg1)
00606 { PThread::Resume(); }
00607 PThreadObj1Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00608 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00609 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00610 obj(_obj), fn(_fn), arg1(_arg1)
00611 { PThread::Resume(); }
00612 void Main()
00613 { (obj.*fn)(arg1); }
00614
00615 protected:
00616 ObjType & obj;
00617 ObjTypeFn fn;
00618 Arg1Type arg1;
00619 };
00620
00621 template <class ObjType, typename Arg1Type, typename Arg2Type>
00622 class PThreadObj2Arg : public PThread
00623 {
00624 PCLASSINFO(PThreadObj2Arg, PThread);
00625 public:
00626 typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
00627 PThreadObj2Arg(ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00628 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00629 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00630 { PThread::Resume(); }
00631 PThreadObj2Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00632 : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00633 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00634 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00635 { PThread::Resume(); }
00636 void Main()
00637 { (obj.*fn)(arg1, arg2); }
00638
00639 protected:
00640 ObjType & obj;
00641 ObjTypeFn fn;
00642 Arg1Type arg1;
00643 Arg1Type arg2;
00644 };
00645
00646
00648
00649
00650
00651
00652 #ifdef _WIN32
00653
00654 #define P_HAS_THREADLOCAL_STORAGE 1
00655
00656 template <class Storage_T>
00657 class PThreadLocalStorage
00658 {
00659 public:
00660 typedef DWORD Key_T;
00661 typedef Storage_T value_type;
00662
00663 PThreadLocalStorage()
00664 { key = TlsAlloc(); }
00665
00666 ~PThreadLocalStorage()
00667 { TlsFree(key); }
00668
00669 Key_T GetKey() const
00670 { return key; }
00671
00672 value_type * Get()
00673 { return (value_type *) TlsGetValue(key); }
00674
00675 void Set(value_type * v)
00676 { TlsSetValue(key, (LPVOID)v); }
00677
00678 protected:
00679 DWORD key;
00680 };
00681
00682 #elif defined(P_PTHREADS)
00683
00684 #include <pthread.h>
00685
00686 #define P_HAS_THREADLOCAL_STORAGE 1
00687
00688 template <class Storage_T>
00689 class PThreadLocalStorage
00690 {
00691 public:
00692 typedef pthread_key_t Key_T;
00693 typedef Storage_T value_type;
00694
00695 PThreadLocalStorage()
00696 { pthread_key_create(&key, NULL); }
00697
00698 ~PThreadLocalStorage()
00699 { pthread_key_delete(key); }
00700
00701 Key_T GetKey() const
00702 { return key; }
00703
00704 value_type * Get()
00705 { return (value_type *)pthread_getspecific(key); }
00706
00707 void Set(value_type * v)
00708 { pthread_setspecific(key, v); }
00709
00710 private:
00711 Key_T key;
00712 };
00713
00714 #else
00715
00716 #undef P_HAS_THREADLOCAL_STORAGE 1
00717 #warning("Thread local storage not supported");
00718
00719 #endif
00720
00721
00722 #ifdef _MSC_VER
00723 #pragma warning(default:4355)
00724 #endif
00725
00726 #endif // _PTHREAD
00727
00728