PTLib  Version 2.10.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
thread.h
Go to the documentation of this file.
1 /*
2  * thread.h
3  *
4  * Executable thread encapsulation class (pre-emptive if OS allows).
5  *
6  * Portable Tools Library
7  *
8  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25  * All Rights Reserved.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Revision: 28050 $
30  * $Author: rjongbloed $
31  * $Date: 2012-07-18 02:15:30 -0500 (Wed, 18 Jul 2012) $
32  */
33 
34 #ifndef PTLIB_THREAD_H
35 #define PTLIB_THREAD_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 #ifdef Priority
42 #undef Priority
43 #endif
44 
45 #include <ptlib/mutex.h>
46 
47 class PSemaphore;
48 
49 
51 // PThread
52 
66 class PThread : public PObject
67 {
68  PCLASSINFO(PThread, PObject);
69 
70  public:
73 
74  enum Priority {
76 
78 
80 
82 
84 
86  };
87 
92 
95  };
96 
119  PThread(
120  PINDEX,
121  AutoDeleteFlag deletion = AutoDeleteThread,
123  Priority priorityLevel = NormalPriority,
124  const PString & threadName = PString::Empty()
125  );
126 
134  ~PThread();
136 
143  void PrintOn(
144  ostream & strm
145  ) const;
147 
155  virtual void Restart();
156 
168  virtual void Terminate();
169 
175  virtual PBoolean IsTerminated() const;
176 
179  void WaitForTermination() const;
180 
187  const PTimeInterval & maxWait
188  ) const;
189 
202  virtual void Suspend(
203  PBoolean susp = true
204  );
205 
225  virtual void Resume();
226 
234  virtual PBoolean IsSuspended() const;
235 
237  static void Sleep(
238  const PTimeInterval & delay
239  );
240 
244  virtual void SetPriority(
245  Priority priorityLevel
246  );
247 
253  virtual Priority GetPriority() const;
254 
258  virtual void SetAutoDelete(
259  AutoDeleteFlag deletion = AutoDeleteThread
260  );
261 
266 
272  virtual PString GetThreadName() const;
273 
279  virtual void SetThreadName(
280  const PString & name
281  );
283 
291  virtual PThreadIdentifier GetThreadId() const { return m_threadId; }
292  static PThreadIdentifier GetCurrentThreadId();
293 
295  struct Times
296  {
300  friend ostream & operator<<(ostream & strm, const Times & times);
301  };
302 
305  bool GetTimes(
306  Times & times
307  );
308 
316  virtual void Main() = 0;
317 
327  static PThread * Current();
328 
335  static void Yield();
336 
341  static PThread * Create(
342  const PNotifier & notifier,
343  INT parameter = 0,
344  AutoDeleteFlag deletion = AutoDeleteThread,
346  Priority priorityLevel = NormalPriority,
347  const PString & threadName = PString::Empty(),
348  PINDEX stackSize = 65536
349  );
350  static PThread * Create(
351  const PNotifier & notifier,
352  const PString & threadName
353  ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
355 
356  bool IsAutoDelete() const { return m_autoDelete; }
357 
358  private:
359  PThread(bool isProcess);
360  // Create a new thread instance as part of a <code>PProcess</code> class.
361 
362  friend class PProcess;
363  friend class PExternalThread;
364  friend class PHouseKeepingThread;
365  // So a PProcess can get at PThread() constructor but nothing else.
366 
367  PThread(const PThread &) : PObject () { }
368  // Empty constructor to prevent copying of thread instances.
369 
370  PThread & operator=(const PThread &) { return *this; }
371  // Empty assignment operator to prevent copying of thread instances.
372 
373  protected:
375  bool m_autoDelete; // Automatically delete the thread on completion.
377 
378  PString m_threadName; // Give the thread a name for debugging purposes.
380 
381  PThreadIdentifier m_threadId;
382 
383 #if PTRACING
384  public:
385  struct TraceInfo {
386  TraceInfo()
387  { traceBlockIndentLevel = 0; }
388 
389  PStack<PStringStream> traceStreams;
390  unsigned traceLevel;
391  unsigned traceBlockIndentLevel;
392  };
393 
394 #ifndef P_HAS_THREADLOCAL_STORAGE
395  private:
396  friend class PTrace;
397  TraceInfo traceInfo;
398 #endif // P_HAS_THREADLOCAL_STORAGE
399 #endif // PTRACING
400 
401 // Include platform dependent part of class
402 #ifdef _WIN32
403 #include "msos/ptlib/thread.h"
404 #else
405 #include "unix/ptlib/thread.h"
406 #endif
407 };
408 
409 // Include definition of platform dependent thread ID format
410 #if defined(_WIN32) && !defined(_WIN32_WCE)
411  #define PTHREAD_ID_FMT "%u"
412 #else
413  #define PTHREAD_ID_FMT "0x%lx"
414 #endif
415 
416 #ifdef _MSC_VER
417 #pragma warning(disable:4355)
418 #endif
419 
424 /*
425  This class automates calling a global function with no arguments within it's own thread.
426  It is used as follows:
427 
428  void GlobalFunction()
429  {
430  }
431 
432  ...
433  PString arg;
434  new PThreadMain(&GlobalFunction)
435  */
436 class PThreadMain : public PThread
437 {
438  PCLASSINFO(PThreadMain, PThread);
439  public:
440  typedef void (*FnType)();
441  PThreadMain(FnType function, bool autoDel = false)
443  , m_function(function)
444  { PThread::Resume(); }
445  PThreadMain(const char * file, int line, FnType function, bool autoDel = false)
447  psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
448  , m_function(function)
449  { PThread::Resume(); }
450  virtual void Main()
451  { (*m_function)(); }
452 
453  protected:
455 };
456 
457 /*
458  This template automates calling a global function with one argument within it's own thread.
459  It is used as follows:
460 
461  void GlobalFunction(PString arg)
462  {
463  }
464 
465  ...
466  PString arg;
467  new PThread1Arg<PString>(arg, &GlobalFunction)
468  */
469 template<typename Arg1Type>
470 class PThread1Arg : public PThread
471 {
472  PCLASSINFO(PThread1Arg, PThread);
473  public:
474  typedef void (*FnType)(Arg1Type arg1);
475 
476  PThread1Arg(Arg1Type arg1, FnType function, bool autoDel = false)
478  , m_function(function)
479  , m_arg1(arg1)
480  { PThread::Resume(); }
481  PThread1Arg(const char * file, int line, Arg1Type arg1, FnType function, bool autoDel = false)
483  psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
484  , m_function(function)
485  , m_arg1(arg1)
486  { PThread::Resume(); }
487  virtual void Main()
488  { (*m_function)(m_arg1); }
489 
490  protected:
492  Arg1Type m_arg1;
493 };
494 
495 
496 /*
497  This template automates calling a global function with two arguments within it's own thread.
498  It is used as follows:
499 
500  void GlobalFunction(PString arg1, int arg2)
501  {
502  }
503 
504  ...
505  PString arg;
506  new PThread2Arg<PString, int>(arg1, arg2, &GlobalFunction)
507  */
508 template<typename Arg1Type, typename Arg2Type>
509 class PThread2Arg : public PThread
510 {
511  PCLASSINFO(PThread2Arg, PThread);
512  public:
513  typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
514  PThread2Arg(Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
516  , m_function(function)
517  , m_arg1(arg1)
518  , m_arg2(arg2)
519  { PThread::Resume(); }
520  PThread2Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, FnType function, bool autoDel = false)
522  psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
523  , m_function(function)
524  , m_arg1(arg1)
525  , m_arg2(arg2)
526  { PThread::Resume(); }
527  virtual void Main()
528  { (*m_function)(m_arg1, m_arg2); }
529 
530  protected:
532  Arg1Type m_arg1;
533  Arg2Type m_arg2;
534 };
535 
536 /*
537  This template automates calling a global function with three arguments within it's own thread.
538  It is used as follows:
539 
540  void GlobalFunction(PString arg1, int arg2, int arg3)
541  {
542  }
543 
544  ...
545  PString arg;
546  new PThread3Arg<PString, int, int>(arg1, arg2, arg3, &GlobalFunction)
547  */
548 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
549 class PThread3Arg : public PThread
550 {
551  PCLASSINFO(PThread3Arg, PThread);
552  public:
553  typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
554  PThread3Arg(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
556  , m_function(function)
557  , m_arg1(arg1)
558  , m_arg2(arg2)
559  , m_arg3(arg3)
560  { PThread::Resume(); }
561  PThread3Arg(const char * file, int line, Arg1Type arg1, Arg2Type arg2, Arg3Type arg3, FnType function, bool autoDel = false)
563  psprintf("%s:%08x-%s:%i", GetClass(), (void *)this, file, line))
564  , m_function(function)
565  , m_arg1(arg1)
566  , m_arg2(arg2)
567  , m_arg3(arg3)
568  { PThread::Resume(); }
569  virtual void Main()
570  { (*m_function)(m_arg1, m_arg2, m_arg3); }
571 
572  protected:
574  Arg1Type m_arg1;
575  Arg2Type m_arg2;
576  Arg2Type m_arg3;
577 };
578 
579 /*
580  This template automates calling a member function with no arguments within it's own thread.
581  It is used as follows:
582 
583  class Example {
584  public:
585  void Function()
586  {
587  }
588  };
589 
590  ...
591  Example ex;
592  new PThreadObj<Example>(ex, &Example::Function)
593  */
594 
595 template <typename ObjType>
596 class PThreadObj : public PThread
597 {
598  PCLASSINFO(PThreadObj, PThread);
599  public:
600  typedef void (ObjType::*ObjTypeFn)();
601 
603  ObjType & obj,
604  ObjTypeFn function,
605  bool autoDel = false,
606  const char * name = NULL,
608  ) : PThread(10000,
610  priority,
611  name)
612  , m_object(obj)
613  , m_function(function)
614  {
615  PThread::Resume();
616  }
617 
618  void Main()
619  {
620  (m_object.*m_function)();
621  }
622 
623  protected:
624  ObjType & m_object;
626 };
627 
628 
629 /*
630  This template automates calling a member function with one argument within it's own thread.
631  It is used as follows:
632 
633  class Example {
634  public:
635  void Function(PString arg)
636  {
637  }
638  };
639 
640  ...
641  Example ex;
642  PString str;
643  new PThreadObj1Arg<Example>(ex, str, &Example::Function)
644  */
645 template <class ObjType, typename Arg1Type>
646 class PThreadObj1Arg : public PThread
647 {
648  PCLASSINFO(PThreadObj1Arg, PThread);
649  public:
650  typedef void (ObjType::*ObjTypeFn)(Arg1Type);
651 
653  ObjType & obj,
654  Arg1Type arg1,
655  ObjTypeFn function,
656  bool autoDel = false,
657  const char * name = NULL,
659  ) : PThread(10000,
661  priority,
662  name)
663  , m_object(obj)
664  , m_function(function)
665  , m_arg1(arg1)
666  {
667  PThread::Resume();
668  }
669 
670  void Main()
671  {
673  }
674 
675  protected:
676  ObjType & m_object;
678  Arg1Type m_arg1;
679 };
680 
681 template <class ObjType, typename Arg1Type, typename Arg2Type>
682 class PThreadObj2Arg : public PThread
683 {
684  PCLASSINFO(PThreadObj2Arg, PThread);
685  public:
686  typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
687 
689  ObjType & obj,
690  Arg1Type arg1,
691  Arg2Type arg2,
692  ObjTypeFn function,
693  bool autoDel = false,
694  const char * name = NULL,
696  ) : PThread(10000,
698  priority,
699  name)
700  , m_object(obj)
701  , m_function(function)
702  , m_arg1(arg1)
703  , m_arg2(arg2)
704  {
705  PThread::Resume();
706  }
707 
708  void Main()
709  {
711  }
712 
713  protected:
714  ObjType & m_object;
716  Arg1Type m_arg1;
717  Arg2Type m_arg2;
718 };
719 
720 
722 //
723 // PThreadLocalStorage
724 //
725 
726 #ifdef _WIN32
727 
728 #define P_HAS_THREADLOCAL_STORAGE 1
729 
730 template <class Storage_T>
731 class PThreadLocalStorage
732 {
733  public:
734  typedef DWORD Key_T;
735  typedef Storage_T value_type;
736 
737  PThreadLocalStorage()
738  { key = TlsAlloc(); }
739 
740  ~PThreadLocalStorage()
741  { TlsFree(key); }
742 
743  Key_T GetKey() const
744  { return key; }
745 
746  value_type * Get()
747  { return (value_type *) TlsGetValue(key); }
748 
749  void Set(value_type * v)
750  { TlsSetValue(key, (LPVOID)v); }
751 
752  protected:
753  DWORD key;
754 };
755 
756 #elif defined(P_PTHREADS)
757 
758 #include <pthread.h>
759 
760 #define P_HAS_THREADLOCAL_STORAGE 1
761 
762 template <class Storage_T>
763 class PThreadLocalStorage
764 {
765  public:
766  typedef pthread_key_t Key_T;
767  typedef Storage_T value_type;
768 
769  PThreadLocalStorage()
770  { pthread_key_create(&key, NULL); }
771 
772  ~PThreadLocalStorage()
773  { pthread_key_delete(key); }
774 
775  Key_T GetKey() const
776  { return key; }
777 
778  value_type * Get()
779  { return (value_type *)pthread_getspecific(key); }
780 
781  void Set(value_type * v)
782  { pthread_setspecific(key, v); }
783 
784  private:
785  Key_T key;
786 };
787 
788 #else
789 
790 #undef P_HAS_THREADLOCAL_STORAGE 1
791 #warning("Thread local storage not supported");
792 
793 #endif
794 
795 
796 #ifdef _MSC_VER
797 #pragma warning(default:4355)
798 #endif
799 
800 #endif // PTLIB_THREAD_H
801 
802 // End Of File ///////////////////////////////////////////////////////////////