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: 21069 $
00030  * $Author: rjongbloed $
00031  * $Date: 2008-09-18 22:59:00 +0000 (Thu, 18 Sep 2008) $
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 // 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 = PTrue    
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 
00304     virtual void Main() = 0;
00305 
00315     static PThread * Current();
00316 
00323     static void Yield();
00324 
00329     static PThread * Create(
00330       const PNotifier & notifier,     
00331       INT parameter = 0,              
00332       AutoDeleteFlag deletion = AutoDeleteThread,
00334       Priority priorityLevel = NormalPriority,  
00335       const PString & threadName = PString::Empty(), 
00336       PINDEX stackSize = 65536         
00337     );
00338     static PThread * Create(
00339       const PNotifier & notifier,     
00340       const PString & threadName      
00341     ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
00343 
00344   protected:
00345     void InitialiseProcessThread();
00346     /* Initialialise the primordial thread, the one in the PProcess. This is
00347        required due to the bootstrap logic of processes and threads.
00348      */
00349 
00350   private:
00351     PThread();
00352     // Create a new thread instance as part of a #PProcess class.
00353 
00354     friend class PProcess;
00355     // So a PProcess can get at PThread() constructor but nothing else.
00356 
00357     PThread(const PThread &) : PObject () { }
00358     // Empty constructor to prevent copying of thread instances.
00359 
00360     PThread & operator=(const PThread &) { return *this; }
00361     // Empty assignment operator to prevent copying of thread instances.
00362 
00363     PBoolean autoDelete;
00364     // Automatically delete the thread on completion.
00365 
00366     // Give the thread a name for debugging purposes.
00367     PString threadName;
00368     PMutex threadNameMutex;
00369 
00370 #if PTRACING
00371   public:
00372     struct TraceInfo {
00373       TraceInfo()
00374       { traceBlockIndentLevel = 0; }
00375 
00376       PStack<PStringStream> traceStreams;
00377       unsigned traceLevel;
00378       unsigned traceBlockIndentLevel;
00379     };
00380 
00381 #ifndef P_HAS_THREADLOCAL_STORAGE
00382   private:
00383     friend class PTrace;
00384     TraceInfo traceInfo;
00385 #endif // P_HAS_THREADLOCAL_STORAGE
00386 #endif // PTRACING
00387 
00388 // Include platform dependent part of class
00389 #ifdef _WIN32
00390 #include "msos/ptlib/thread.h"
00391 #else
00392 #include "unix/ptlib/thread.h"
00393 #endif
00394 };
00395 
00396 // Include definition of platform dependent thread ID format
00397 #if defined(_WIN32) && !defined(_WIN32_WCE)
00398   #define PTHREAD_ID_FMT ":%u"
00399 #else
00400   #define PTHREAD_ID_FMT ":0x%x"
00401 #endif
00402 
00403 #ifdef _MSC_VER
00404 #pragma warning(disable:4355)
00405 #endif
00406 
00411 /*
00412    This class automates calling a global function with no arguments within it's own thread.
00413    It is used as follows:
00414 
00415    void GlobalFunction()
00416    {
00417    }
00418 
00419    ...
00420    PString arg;
00421    new PThreadMain(&GlobalFunction)
00422  */
00423 class PThreadMain : public PThread
00424 {
00425   PCLASSINFO(PThreadMain, PThread);
00426   public:
00427     typedef void (*FnType)(); 
00428     PThreadMain(FnType _fn, PBoolean _autoDelete = PFalse)
00429       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn)
00430     { PThread::Resume(); }
00431     PThreadMain(const char * _file, int _line, FnType _fn, PBoolean _autoDelete = PFalse)
00432       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,  NormalPriority,
00433         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn)
00434     { PThread::Resume(); }
00435     virtual void Main()
00436     { (*fn)(); }
00437     FnType fn;
00438 };
00439 
00440 /*
00441    This template automates calling a global function with one argument within it's own thread.
00442    It is used as follows:
00443 
00444    void GlobalFunction(PString arg)
00445    {
00446    }
00447 
00448    ...
00449    PString arg;
00450    new PThread1Arg<PString>(arg, &GlobalFunction)
00451  */
00452 template<typename Arg1Type>
00453 class PThread1Arg : public PThread
00454 {
00455   PCLASSINFO(PThread1Arg, PThread);
00456   public:
00457     typedef void (*FnType)(Arg1Type arg1); 
00458     PThread1Arg(Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00459       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00460         arg1(_arg1)
00461     { PThread::Resume(); }
00462     PThread1Arg(const char * _file, int _line, Arg1Type _arg1, FnType _fn, PBoolean _autoDelete = PFalse)
00463       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,  NormalPriority,
00464         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00465         arg1(_arg1)
00466     { PThread::Resume(); }
00467     virtual void Main()
00468     { (*fn)(arg1); }
00469     FnType fn;
00470     Arg1Type arg1;
00471 };
00472 
00473 
00474 /*
00475    This template automates calling a global function with two arguments within it's own thread.
00476    It is used as follows:
00477 
00478    void GlobalFunction(PString arg1, int arg2)
00479    {
00480    }
00481 
00482    ...
00483    PString arg;
00484    new PThread2Arg<PString, int>(arg1, arg2, &GlobalFunction)
00485  */
00486 template<typename Arg1Type, typename Arg2Type>
00487 class PThread2Arg : public PThread
00488 {
00489   PCLASSINFO(PThread2Arg, PThread);
00490   public:
00491     typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2); 
00492     PThread2Arg(Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00493       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00494         arg1(_arg1), arg2(_arg2)
00495     { PThread::Resume(); }
00496     PThread2Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, FnType _fn, PBoolean _autoDelete = PFalse)
00497       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00498         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00499         arg1(_arg1), arg2(_arg2)
00500     { PThread::Resume(); }
00501     virtual void Main()
00502     { (*fn)(arg1, arg2); }
00503     FnType fn;
00504     Arg1Type arg1;
00505     Arg2Type arg2;
00506 };
00507 
00508 /*
00509    This template automates calling a global function with three arguments within it's own thread.
00510    It is used as follows:
00511 
00512    void GlobalFunction(PString arg1, int arg2, int arg3)
00513    {
00514    }
00515 
00516    ...
00517    PString arg;
00518    new PThread3Arg<PString, int, int>(arg1, arg2, arg3, &GlobalFunction)
00519  */
00520 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
00521 class PThread3Arg : public PThread
00522 {
00523   PCLASSINFO(PThread3Arg, PThread);
00524   public:
00525     typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3); 
00526     PThread3Arg(Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00527       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread), fn(_fn),
00528         arg1(_arg1), arg2(_arg2), arg3(_arg3)
00529     { PThread::Resume(); }
00530     PThread3Arg(const char * _file, int _line, Arg1Type _arg1, Arg2Type _arg2, Arg3Type _arg3, FnType _fn, PBoolean _autoDelete = PFalse)
00531       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00532         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)), fn(_fn),
00533         arg1(_arg1), arg2(_arg2), arg3(_arg3)
00534     { PThread::Resume(); }
00535     virtual void Main()
00536     { (*fn)(arg1, arg2, arg3); }
00537     FnType fn;
00538     Arg1Type arg1;
00539     Arg2Type arg2;
00540     Arg2Type arg3;
00541 };
00542 
00543 /*
00544    This template automates calling a member function with no arguments within it's own thread.
00545    It is used as follows:
00546 
00547    class Example {
00548      public:
00549       void Function()
00550       {
00551       }
00552    };
00553 
00554    ...
00555    Example ex;
00556    new PThreadObj<Example>(ex, &Example::Function)
00557  */
00558 
00559 template <typename ObjType>
00560 class PThreadObj : public PThread
00561 {
00562   public:
00563   PCLASSINFO(PThreadObj, PThread);
00564   public:
00565     typedef void (ObjType::*ObjTypeFn)(); 
00566     PThreadObj(ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00567       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00568         obj(_obj), fn(_fn)
00569     { PThread::Resume(); }
00570     PThreadObj(const char * _file, int _line, ObjType & _obj, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00571       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00572         psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00573         obj(_obj), fn(_fn)
00574     { PThread::Resume(); }
00575     void Main()
00576     { (obj.*fn)(); }
00577 
00578   protected:
00579     ObjType & obj;
00580     ObjTypeFn fn;
00581 };
00582 
00583 
00584 /*
00585    This template automates calling a member function with one argument within it's own thread.
00586    It is used as follows:
00587 
00588    class Example {
00589      public:
00590       void Function(PString arg)
00591       {
00592       }
00593    };
00594 
00595    ...
00596    Example ex;
00597    PString str;
00598    new PThreadObj1Arg<Example>(ex, str, &Example::Function)
00599  */
00600 template <class ObjType, typename Arg1Type>
00601 class PThreadObj1Arg : public PThread
00602 {
00603   PCLASSINFO(PThreadObj1Arg, PThread);
00604   public:
00605     typedef void (ObjType::*ObjTypeFn)(Arg1Type); 
00606     PThreadObj1Arg(ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00607       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00608                                 obj(_obj), fn(_fn), arg1(_arg1)
00609     { PThread::Resume(); }
00610     PThreadObj1Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00611       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00612                                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00613                                 obj(_obj), fn(_fn), arg1(_arg1)
00614     { PThread::Resume(); }
00615     void Main()
00616     { (obj.*fn)(arg1); }
00617 
00618   protected:
00619     ObjType & obj;
00620     ObjTypeFn fn;
00621     Arg1Type arg1;
00622 };
00623 
00624 template <class ObjType, typename Arg1Type, typename Arg2Type>
00625 class PThreadObj2Arg : public PThread
00626 {
00627   PCLASSINFO(PThreadObj2Arg, PThread);
00628   public:
00629     typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type); 
00630     PThreadObj2Arg(ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00631       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread),
00632                                 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00633     { PThread::Resume(); }
00634     PThreadObj2Arg(const char * _file, int _line, ObjType & _obj, Arg1Type _arg1, Arg2Type _arg2, ObjTypeFn _fn, PBoolean _autoDelete = PFalse)
00635       : PThread(10000, _autoDelete ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, NormalPriority,
00636                                 psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, _file, _line)),
00637                                 obj(_obj), fn(_fn), arg1(_arg1), arg2(_arg2)
00638     { PThread::Resume(); }
00639     void Main()
00640     { (obj.*fn)(arg1, arg2); }
00641 
00642   protected:
00643     ObjType & obj;
00644     ObjTypeFn fn;
00645     Arg1Type arg1;
00646     Arg1Type arg2;
00647 };
00648 
00649 
00651 //
00652 // PThreadLocalStorage
00653 //
00654 
00655 #ifdef _WIN32
00656 
00657 #define P_HAS_THREADLOCAL_STORAGE 1
00658 
00659 template <class Storage_T>
00660 class PThreadLocalStorage
00661 {
00662   public:
00663     typedef DWORD Key_T;
00664     typedef Storage_T value_type;
00665 
00666     PThreadLocalStorage()
00667     { key = TlsAlloc(); }
00668 
00669     ~PThreadLocalStorage()
00670     { TlsFree(key);  }
00671 
00672     Key_T GetKey() const
00673     { return key; }
00674 
00675     value_type * Get()
00676     { return (value_type *) TlsGetValue(key); }
00677 
00678     void Set(value_type * v)
00679     { TlsSetValue(key, (LPVOID)v); }
00680 
00681   protected:
00682     DWORD key;
00683 };
00684 
00685 #elif defined(P_PTHREADS)
00686 
00687 #include <pthread.h>
00688 
00689 #define P_HAS_THREADLOCAL_STORAGE 1
00690 
00691 template <class Storage_T>
00692 class PThreadLocalStorage
00693 {
00694   public:
00695     typedef pthread_key_t Key_T;
00696     typedef Storage_T value_type;
00697 
00698     PThreadLocalStorage()
00699     { pthread_key_create(&key, NULL); }
00700 
00701     ~PThreadLocalStorage()
00702     { pthread_key_delete(key); }
00703 
00704     Key_T GetKey() const
00705     { return key; }
00706 
00707     value_type * Get()
00708     { return (value_type *)pthread_getspecific(key); }
00709 
00710     void Set(value_type * v)
00711     { pthread_setspecific(key, v); }
00712 
00713   private:
00714     Key_T key;
00715 };
00716 
00717 #else
00718 
00719 #undef P_HAS_THREADLOCAL_STORAGE 1
00720 #warning("Thread local storage not supported");
00721 
00722 #endif
00723 
00724 
00725 #ifdef _MSC_VER
00726 #pragma warning(default:4355)
00727 #endif
00728 
00729 #endif // _PTHREAD
00730 
00731 // End Of File ///////////////////////////////////////////////////////////////

Generated on Mon Feb 23 01:57:54 2009 for PTLib by  doxygen 1.5.1