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: 24177 $
00030  * $Author: rjongbloed $
00031  * $Date: 2010-04-05 06:52:04 -0500 (Mon, 05 Apr 2010) $
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 #define PThreadIdentifer PThreadIdentifier
00050 
00051 typedef P_THREADIDENTIFIER PThreadIdentifier;
00052 
00054 // PThread
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 
00182     void WaitForTermination() const;
00183 
00189     PBoolean WaitForTermination(
00190       const PTimeInterval & maxWait  
00191     ) const;
00192 
00205     virtual void Suspend(
00206       PBoolean susp = true    
00207     );
00208 
00228     virtual void Resume();
00229 
00237     virtual PBoolean IsSuspended() const;
00238 
00240     static void Sleep(
00241       const PTimeInterval & delay   
00242     );
00243 
00247     virtual void SetPriority(
00248       Priority priorityLevel    
00249     );
00250 
00256     virtual Priority GetPriority() const;
00257 
00261     virtual void SetAutoDelete(
00262       AutoDeleteFlag deletion = AutoDeleteThread  
00263     );
00264 
00268     void SetNoAutoDelete() { SetAutoDelete(NoAutoDeleteThread); }
00269 
00275     virtual PString GetThreadName() const;
00276 
00282     virtual void SetThreadName(
00283       const PString & name        
00284     );
00286 
00294     virtual PThreadIdentifier GetThreadId() const;
00295     static PThreadIdentifier GetCurrentThreadId();
00296 
00298     struct Times
00299     {
00300       PTimeInterval m_real;     
00301       PTimeInterval m_kernel;   
00302       PTimeInterval m_user;     
00303       friend ostream & operator<<(ostream & strm, const Times & times);
00304     };
00305 
00308     bool GetTimes(
00309       Times & times   
00310     );
00311 
00319     virtual void Main() = 0;
00320 
00330     static PThread * Current();
00331 
00338     static void Yield();
00339 
00344     static PThread * Create(
00345       const PNotifier & notifier,     
00346       INT parameter = 0,              
00347       AutoDeleteFlag deletion = AutoDeleteThread,
00349       Priority priorityLevel = NormalPriority,  
00350       const PString & threadName = PString::Empty(), 
00351       PINDEX stackSize = 65536         
00352     );
00353     static PThread * Create(
00354       const PNotifier & notifier,     
00355       const PString & threadName      
00356     ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00358   
00359     bool IsAutoDelete() const { return autoDelete; }
00360 
00361   private:
00362     PThread();
00363     // Create a new thread instance as part of a <code>PProcess</code> class.
00364 
00365     friend class PProcess;
00366     friend class PExternalThread;
00367     friend class PHouseKeepingThread;
00368     // So a PProcess can get at PThread() constructor but nothing else.
00369 
00370     PThread(const PThread &) : PObject () { }
00371     // Empty constructor to prevent copying of thread instances.
00372 
00373     PThread & operator=(const PThread &) { return *this; }
00374     // Empty assignment operator to prevent copying of thread instances.
00375 
00376     PBoolean autoDelete;
00377     // Automatically delete the thread on completion.
00378 
00379     // Give the thread a name for debugging purposes.
00380     PString threadName;
00381     PMutex threadNameMutex;
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%x"
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 Oct 14 01:44:10 2011 for PTLib by  doxygen 1.4.7