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 PTLIB_THREAD_H
00035 #define PTLIB_THREAD_H
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
00051
00052
00066 class PThread : public PObject
00067 {
00068 PCLASSINFO(PThread, PObject);
00069
00070 public:
00073
00074 enum Priority {
00075 LowestPriority,
00076
00077 LowPriority,
00078
00079 NormalPriority,
00080
00081 HighPriority,
00082
00083 HighestPriority,
00084
00085 NumPriorities
00086 };
00087
00089 enum AutoDeleteFlag {
00091 AutoDeleteThread,
00092
00094 NoAutoDeleteThread
00095 };
00096
00119 PThread(
00120 PINDEX,
00121 AutoDeleteFlag deletion = AutoDeleteThread,
00123 Priority priorityLevel = NormalPriority,
00124 const PString & threadName = PString::Empty()
00125 );
00126
00134 ~PThread();
00136
00143 void PrintOn(
00144 ostream & strm
00145 ) const;
00147
00155 virtual void Restart();
00156
00168 virtual void Terminate();
00169
00175 virtual PBoolean IsTerminated() const;
00176
00179 void WaitForTermination() const;
00180
00186 PBoolean WaitForTermination(
00187 const PTimeInterval & maxWait
00188 ) const;
00189
00202 virtual void Suspend(
00203 PBoolean susp = true
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 { return m_threadId; }
00292 static PThreadIdentifier GetCurrentThreadId();
00293
00295 struct Times
00296 {
00297 PTimeInterval m_real;
00298 PTimeInterval m_kernel;
00299 PTimeInterval m_user;
00300 friend ostream & operator<<(ostream & strm, const Times & times);
00301 };
00302
00305 bool GetTimes(
00306 Times & times
00307 );
00308
00316 virtual void Main() = 0;
00317
00327 static PThread * Current();
00328
00335 static void Yield();
00336
00341 static PThread * Create(
00342 const PNotifier & notifier,
00343 INT parameter = 0,
00344 AutoDeleteFlag deletion = AutoDeleteThread,
00346 Priority priorityLevel = NormalPriority,
00347 const PString & threadName = PString::Empty(),
00348 PINDEX stackSize = 65536
00349 );
00350 static PThread * Create(
00351 const PNotifier & notifier,
00352 const PString & threadName
00353 ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00355
00356 bool IsAutoDelete() const { return m_autoDelete; }
00357
00358 private:
00359 PThread(bool isProcess);
00360
00361
00362 friend class PProcess;
00363 friend class PExternalThread;
00364 friend class PHouseKeepingThread;
00365
00366
00367 PThread(const PThread &) : PObject () { }
00368
00369
00370 PThread & operator=(const PThread &) { return *this; }
00371
00372
00373 protected:
00374 bool m_isProcess;
00375 bool m_autoDelete;
00376 PINDEX m_originalStackSize;
00377
00378 PString m_threadName;
00379 PMutex m_threadNameMutex;
00380
00381 PThreadIdentifier m_threadId;
00382
00383 #if PTRACING
00384 public:
00385 struct TraceInfo {
00386 TraceInfo()
00387 { traceBlockIndentLevel = 0; }
00388
00389 PStack<PStringStream> traceStreams;
00390 unsigned traceLevel;
00391 unsigned traceBlockIndentLevel;
00392 };
00393
00394 #ifndef P_HAS_THREADLOCAL_STORAGE
00395 private:
00396 friend class PTrace;
00397 TraceInfo traceInfo;
00398 #endif // P_HAS_THREADLOCAL_STORAGE
00399 #endif // PTRACING
00400
00401
00402 #ifdef _WIN32
00403 #include "msos/ptlib/thread.h"
00404 #else
00405 #include "unix/ptlib/thread.h"
00406 #endif
00407 };
00408
00409
00410 #if defined(_WIN32) && !defined(_WIN32_WCE)
00411 #define PTHREAD_ID_FMT "%u"
00412 #else
00413 #define PTHREAD_ID_FMT "0x%lx"
00414 #endif
00415
00416 #ifdef _MSC_VER
00417 #pragma warning(disable:4355)
00418 #endif
00419
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 class PThreadMain : public PThread
00437 {
00438 PCLASSINFO(PThreadMain, PThread);
00439 public:
00440 typedef void (*FnType)();
00441 PThreadMain(FnType function, bool autoDel = false)
00442 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00443 , m_function(function)
00444 { PThread::Resume(); }
00445 PThreadMain(const char * file, int line, FnType function, bool autoDel = false)
00446 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00447 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00448 , m_function(function)
00449 { PThread::Resume(); }
00450 virtual void Main()
00451 { (*m_function)(); }
00452
00453 protected:
00454 FnType m_function;
00455 };
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 template<typename Arg1Type>
00470 class PThread1Arg : public PThread
00471 {
00472 PCLASSINFO(PThread1Arg, PThread);
00473 public:
00474 typedef void (*FnType)(Arg1Type arg1);
00475
00476 PThread1Arg(Arg1Type arg1, FnType function, bool autoDel = false)
00477 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00478 , m_function(function)
00479 , m_arg1(arg1)
00480 { PThread::Resume(); }
00481 PThread1Arg(const char * file, int line, Arg1Type arg1, FnType function, bool autoDel = false)
00482 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00483 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00484 , m_function(function)
00485 , m_arg1(arg1)
00486 { PThread::Resume(); }
00487 virtual void Main()
00488 { (*m_function)(m_arg1); }
00489
00490 protected:
00491 FnType m_function;
00492 Arg1Type m_arg1;
00493 };
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 template<typename Arg1Type, typename Arg2Type>
00509 class PThread2Arg : public PThread
00510 {
00511 PCLASSINFO(PThread2Arg, PThread);
00512 public:
00513 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
00514 PThread2Arg(Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
00515 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00516 , m_function(function)
00517 , m_arg1(arg1)
00518 , m_arg2(arg2)
00519 { PThread::Resume(); }
00520 PThread2Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
00521 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00522 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00523 , m_function(function)
00524 , m_arg1(arg1)
00525 , m_arg2(arg2)
00526 { PThread::Resume(); }
00527 virtual void Main()
00528 { (*m_function)(m_arg1, m_arg2); }
00529
00530 protected:
00531 FnType m_function;
00532 Arg1Type m_arg1;
00533 Arg2Type m_arg2;
00534 };
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00549 class PThread3Arg : public PThread
00550 {
00551 PCLASSINFO(PThread3Arg, PThread);
00552 public:
00553 typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
00554 PThread3Arg(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
00555 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
00556 , m_function(function)
00557 , m_arg1(arg1)
00558 , m_arg2(arg2)
00559 , m_arg3(arg3)
00560 { PThread::Resume(); }
00561 PThread3Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
00562 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00563 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
00564 , m_function(function)
00565 , m_arg1(arg1)
00566 , m_arg2(arg2)
00567 , m_arg3(arg3)
00568 { PThread::Resume(); }
00569 virtual void Main()
00570 { (*m_function)(m_arg1, m_arg2, m_arg3); }
00571
00572 protected:
00573 FnType m_function;
00574 Arg1Type m_arg1;
00575 Arg2Type m_arg2;
00576 Arg2Type m_arg3;
00577 };
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 template <typename ObjType>
00596 class PThreadObj : public PThread
00597 {
00598 PCLASSINFO(PThreadObj, PThread);
00599 public:
00600 typedef void (ObjType::*ObjTypeFn)();
00601
00602 PThreadObj(
00603 ObjType & obj,
00604 ObjTypeFn function,
00605 bool autoDel = false,
00606 const char * name = NULL,
00607 PThread::Priority priority = PThread::NormalPriority
00608 ) : PThread(10000,
00609 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00610 priority,
00611 name)
00612 , m_object(obj)
00613 , m_function(function)
00614 {
00615 PThread::Resume();
00616 }
00617
00618 void Main()
00619 {
00620 (m_object.*m_function)();
00621 }
00622
00623 protected:
00624 ObjType & m_object;
00625 ObjTypeFn m_function;
00626 };
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 template <class ObjType, typename Arg1Type>
00646 class PThreadObj1Arg : public PThread
00647 {
00648 PCLASSINFO(PThreadObj1Arg, PThread);
00649 public:
00650 typedef void (ObjType::*ObjTypeFn)(Arg1Type);
00651
00652 PThreadObj1Arg(
00653 ObjType & obj,
00654 Arg1Type arg1,
00655 ObjTypeFn function,
00656 bool autoDel = false,
00657 const char * name = NULL,
00658 PThread::Priority priority = PThread::NormalPriority
00659 ) : PThread(10000,
00660 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00661 priority,
00662 name)
00663 , m_object(obj)
00664 , m_function(function)
00665 , m_arg1(arg1)
00666 {
00667 PThread::Resume();
00668 }
00669
00670 void Main()
00671 {
00672 (m_object.*m_function)(m_arg1);
00673 }
00674
00675 protected:
00676 ObjType & m_object;
00677 ObjTypeFn m_function;
00678 Arg1Type m_arg1;
00679 };
00680
00681 template <class ObjType, typename Arg1Type, typename Arg2Type>
00682 class PThreadObj2Arg : public PThread
00683 {
00684 PCLASSINFO(PThreadObj2Arg, PThread);
00685 public:
00686 typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
00687
00688 PThreadObj2Arg(
00689 ObjType & obj,
00690 Arg1Type arg1,
00691 Arg2Type arg2,
00692 ObjTypeFn function,
00693 bool autoDel = false,
00694 const char * name = NULL,
00695 PThread::Priority priority = PThread::NormalPriority
00696 ) : PThread(10000,
00697 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
00698 priority,
00699 name)
00700 , m_object(obj)
00701 , m_function(function)
00702 , m_arg1(arg1)
00703 , m_arg2(arg2)
00704 {
00705 PThread::Resume();
00706 }
00707
00708 void Main()
00709 {
00710 (m_object.*m_function)(m_arg1, m_arg2);
00711 }
00712
00713 protected:
00714 ObjType & m_object;
00715 ObjTypeFn m_function;
00716 Arg1Type m_arg1;
00717 Arg2Type m_arg2;
00718 };
00719
00720
00722
00723
00724
00725
00726 #ifdef _WIN32
00727
00728 #define P_HAS_THREADLOCAL_STORAGE 1
00729
00730 template <class Storage_T>
00731 class PThreadLocalStorage
00732 {
00733 public:
00734 typedef DWORD Key_T;
00735 typedef Storage_T value_type;
00736
00737 PThreadLocalStorage()
00738 { key = TlsAlloc(); }
00739
00740 ~PThreadLocalStorage()
00741 { TlsFree(key); }
00742
00743 Key_T GetKey() const
00744 { return key; }
00745
00746 value_type * Get()
00747 { return (value_type *) TlsGetValue(key); }
00748
00749 void Set(value_type * v)
00750 { TlsSetValue(key, (LPVOID)v); }
00751
00752 protected:
00753 DWORD key;
00754 };
00755
00756 #elif defined(P_PTHREADS)
00757
00758 #include <pthread.h>
00759
00760 #define P_HAS_THREADLOCAL_STORAGE 1
00761
00762 template <class Storage_T>
00763 class PThreadLocalStorage
00764 {
00765 public:
00766 typedef pthread_key_t Key_T;
00767 typedef Storage_T value_type;
00768
00769 PThreadLocalStorage()
00770 { pthread_key_create(&key, NULL); }
00771
00772 ~PThreadLocalStorage()
00773 { pthread_key_delete(key); }
00774
00775 Key_T GetKey() const
00776 { return key; }
00777
00778 value_type * Get()
00779 { return (value_type *)pthread_getspecific(key); }
00780
00781 void Set(value_type * v)
00782 { pthread_setspecific(key, v); }
00783
00784 private:
00785 Key_T key;
00786 };
00787
00788 #else
00789
00790 #undef P_HAS_THREADLOCAL_STORAGE 1
00791 #warning("Thread local storage not supported");
00792
00793 #endif
00794
00795
00796 #ifdef _MSC_VER
00797 #pragma warning(default:4355)
00798 #endif
00799
00800 #endif // PTLIB_THREAD_H
00801
00802