thread.h

Go to the documentation of this file.
00001 /*
00002  * thread.h
00003  *
00004  * Executable thread encapsulation class (pre-emptive if OS allows).
00005  *
00006  * Portable Tools Library
00007  *
00008  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Portable Windows Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
00025  * All Rights Reserved.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Revision: 28050 $
00030  * $Author: rjongbloed $
00031  * $Date: 2012-07-18 02:15:30 -0500 (Wed, 18 Jul 2012) $
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 // PThread
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     // Create a new thread instance as part of a <code>PProcess</code> class.
00361 
00362     friend class PProcess;
00363     friend class PExternalThread;
00364     friend class PHouseKeepingThread;
00365     // So a PProcess can get at PThread() constructor but nothing else.
00366 
00367     PThread(const PThread &) : PObject () { }
00368     // Empty constructor to prevent copying of thread instances.
00369 
00370     PThread & operator=(const PThread &) { return *this; }
00371     // Empty assignment operator to prevent copying of thread instances.
00372 
00373   protected:
00374     bool   m_isProcess;
00375     bool   m_autoDelete; // Automatically delete the thread on completion.
00376     PINDEX m_originalStackSize;
00377 
00378     PString m_threadName; // Give the thread a name for debugging purposes.
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 // Include platform dependent part of class
00402 #ifdef _WIN32
00403 #include "msos/ptlib/thread.h"
00404 #else
00405 #include "unix/ptlib/thread.h"
00406 #endif
00407 };
00408 
00409 // Include definition of platform dependent thread ID format
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    This class automates calling a global function with no arguments within it's own thread.
00426    It is used as follows:
00427 
00428    void GlobalFunction()
00429    {
00430    }
00431 
00432    ...
00433    PString arg;
00434    new PThreadMain(&GlobalFunction)
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    This template automates calling a global function with one argument within it's own thread.
00459    It is used as follows:
00460 
00461    void GlobalFunction(PString arg)
00462    {
00463    }
00464 
00465    ...
00466    PString arg;
00467    new PThread1Arg<PString>(arg, &GlobalFunction)
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    This template automates calling a global function with two arguments within it's own thread.
00498    It is used as follows:
00499 
00500    void GlobalFunction(PString arg1, int arg2)
00501    {
00502    }
00503 
00504    ...
00505    PString arg;
00506    new PThread2Arg<PString, int>(arg1, arg2, &GlobalFunction)
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    This template automates calling a global function with three arguments within it's own thread.
00538    It is used as follows:
00539 
00540    void GlobalFunction(PString arg1, int arg2, int arg3)
00541    {
00542    }
00543 
00544    ...
00545    PString arg;
00546    new PThread3Arg<PString, int, int>(arg1, arg2, arg3, &GlobalFunction)
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    This template automates calling a member function with no arguments within it's own thread.
00581    It is used as follows:
00582 
00583    class Example {
00584      public:
00585       void Function()
00586       {
00587       }
00588    };
00589 
00590    ...
00591    Example ex;
00592    new PThreadObj<Example>(ex, &Example::Function)
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    This template automates calling a member function with one argument within it's own thread.
00631    It is used as follows:
00632 
00633    class Example {
00634      public:
00635       void Function(PString arg)
00636       {
00637       }
00638    };
00639 
00640    ...
00641    Example ex;
00642    PString str;
00643    new PThreadObj1Arg<Example>(ex, str, &Example::Function)
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 // PThreadLocalStorage
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 // End Of File ///////////////////////////////////////////////////////////////

Generated on Fri Feb 15 20:58:31 2013 for PTLib by  doxygen 1.4.7