PTLib  Version 2.14.3
 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: 32255 $
30  * $Author: rjongbloed $
31  * $Date: 2014-06-29 17:49:31 +1000 (Sun, 29 Jun 2014) $
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 #include <set>
47 
48 
49 class PSemaphore;
50 
51 
53 // PThread
54 
68 class PThread : public PObject
69 {
70  PCLASSINFO(PThread, PObject);
71 
72  public:
75 
76  enum Priority {
78 
80 
82 
84 
86 
88  };
89 
94 
97  };
98 
120  PThread(
121  PINDEX stack,
122  AutoDeleteFlag deletion = AutoDeleteThread,
124  Priority priorityLevel = NormalPriority,
125  const PString & threadName = PString::Empty()
126  );
127 
135  ~PThread();
137 
144  void PrintOn(
145  ostream & strm
146  ) const;
148 
156  virtual void Restart();
157 
169  virtual void Terminate();
170 
176  virtual PBoolean IsTerminated() const;
177 
180  void WaitForTermination() const;
181 
188  const PTimeInterval & maxWait
189  ) const;
190 
203  virtual void Suspend(
204  PBoolean susp = true
205  );
206 
226  virtual void Resume();
227 
235  virtual PBoolean IsSuspended() const;
236 
238  static void Sleep(
239  const PTimeInterval & delay
240  );
241 
245  virtual void SetPriority(
246  Priority priorityLevel
247  );
248 
254  virtual Priority GetPriority() const;
255 
259  virtual void SetAutoDelete(
260  AutoDeleteFlag deletion = AutoDeleteThread
261  );
262 
267 
273  virtual PString GetThreadName() const;
274 
280  virtual void SetThreadName(
281  const PString & name
282  );
284 
292  virtual PThreadIdentifier GetThreadId() const { return m_threadId; }
293  static PThreadIdentifier GetCurrentThreadId();
294 
296  struct Times
297  {
301  friend ostream & operator<<(ostream & strm, const Times & times);
302  };
303 
306  bool GetTimes(
307  Times & times
308  );
309 
317  virtual void Main() = 0;
318 
328  static PThread * Current();
329 
336  static void Yield();
337 
342  static PThread * Create(
343  const PNotifier & notifier,
344  INT parameter = 0,
345  AutoDeleteFlag deletion = AutoDeleteThread,
347  Priority priorityLevel = NormalPriority,
348  const PString & threadName = PString::Empty(),
349  PINDEX stackSize = 0
350  );
351  static PThread * Create(
352  const PNotifier & notifier,
353  const PString & threadName
354  ) { return Create(notifier, 0, NoAutoDeleteThread, NormalPriority, threadName); }
356 
357  bool IsAutoDelete() const { return m_type == e_IsAutoDelete || m_type == e_IsExternal; }
358 
361  {
362  public:
363  virtual ~LocalStorageBase() { }
364  protected:
366  void StorageDestroyed();
367  virtual void * Allocate() const = 0;
368  virtual void Deallocate(void * ptr) const = 0;
369  virtual void * GetStorage() const;
370  private:
371  void ThreadDestroyed(PThread * thread) const;
372  typedef std::map<PThread *, void *> StorageMap;
373  mutable StorageMap m_storage;
374  PMutex m_mutex;
375  friend class PThread;
376  };
377  friend class LocalStorageBase;
378 
379  private:
380  PThread(bool isProcess);
381  // Create a new thread instance as part of a <code>PProcess</code> class.
382 
383  void InternalDestroy();
384 
385  friend class PProcess;
386  friend class PExternalThread;
387  // So a PProcess can get at PThread() constructor but nothing else.
388 
389  PThread(const PThread &) : PObject () { }
390  // Empty constructor to prevent copying of thread instances.
391 
392  PThread & operator=(const PThread &) { return *this; }
393  // Empty assignment operator to prevent copying of thread instances.
394 
395  protected:
397 
399 
400  PString m_threadName; // Give the thread a name for debugging purposes.
402 
403  PThreadIdentifier m_threadId;
404 
405  typedef std::list<const LocalStorageBase *> LocalStorageList;
407 
408 // Include platform dependent part of class
409 #ifdef _WIN32
410 #include "msos/ptlib/thread.h"
411 #else
412 #include "unix/ptlib/thread.h"
413 #endif
414 };
415 
416 
421 /*
422  This class automates calling a global function with no arguments within it's own thread.
423  It is used as follows:
424 
425  void GlobalFunction()
426  {
427  }
428 
429  ...
430  PString arg;
431  new PThreadMain(&GlobalFunction)
432  */
433 class PThreadMain : public PThread
434 {
435  PCLASSINFO(PThreadMain, PThread);
436  public:
437  typedef void (*FnType)();
438  PThreadMain(FnType function, bool autoDel = false)
440  , m_function(function)
441  {
442  PThread::Resume();
443  }
444 
445  virtual void Main()
446  {
447  (*m_function)();
448  }
449 
450  protected:
452 };
453 
454 
455 /*
456  This template automates calling a global function using a functor
457  It is used as follows:
458 
459  struct Functor {
460  void operator()(PThread & thread) { ... code in here }
461  }
462 
463  ...
464  Functor arg;
465  new PThreadFunctor<Functor>(arg)
466  */
467 template<typename Functor>
468 class PThreadFunctor : public PThread
469 {
470  PCLASSINFO(PThreadFunctor, PThread);
471  public:
472  PThreadFunctor(Functor & funct, bool autoDel = false)
474  , m_funct(funct)
475  {
476  PThread::Resume();
477  }
478 
479  virtual void Main()
480  {
481  m_funct(*this);
482  }
483 
484  protected:
485  Functor & m_funct;
486 };
487 
488 
489 /*
490  This template automates calling a global function with one argument within it's own thread.
491  It is used as follows:
492 
493  void GlobalFunction(PString arg)
494  {
495  }
496 
497  ...
498  PString arg;
499  new PThread1Arg<PString>(arg, &GlobalFunction)
500  */
501 template<typename Arg1Type>
502 class PThread1Arg : public PThread
503 {
504  PCLASSINFO(PThread1Arg, PThread);
505  public:
506  typedef void (*FnType)(Arg1Type arg1);
507 
509  Arg1Type arg1,
510  FnType function,
511  bool autoDel = false,
512  const char * name = NULL,
514  ) : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, priority, name)
515  , m_function(function)
516  , m_arg1(arg1)
517  {
518  PThread::Resume();
519  }
520 
521  virtual void Main()
522  {
523  (*m_function)(m_arg1);
524  }
525 
526  protected:
528  Arg1Type m_arg1;
529 };
530 
531 
532 /*
533  This template automates calling a global function with two arguments within it's own thread.
534  It is used as follows:
535 
536  void GlobalFunction(PString arg1, int arg2)
537  {
538  }
539 
540  ...
541  PString arg;
542  new PThread2Arg<PString, int>(arg1, arg2, &GlobalFunction)
543  */
544 template<typename Arg1Type, typename Arg2Type>
545 class PThread2Arg : public PThread
546 {
547  PCLASSINFO(PThread2Arg, PThread);
548  public:
549  typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2);
551  Arg1Type arg1,
552  Arg2Type arg2,
553  FnType function,
554  bool autoDel = false,
555  const char * name = NULL,
557  ) : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, priority, name)
558  , m_function(function)
559  , m_arg1(arg1)
560  , m_arg2(arg2)
561  {
562  PThread::Resume();
563  }
564 
565  virtual void Main()
566  {
567  (*m_function)(m_arg1, m_arg2);
568  }
569 
570  protected:
572  Arg1Type m_arg1;
573  Arg2Type m_arg2;
574 };
575 
576 /*
577  This template automates calling a global function with three arguments within it's own thread.
578  It is used as follows:
579 
580  void GlobalFunction(PString arg1, int arg2, int arg3)
581  {
582  }
583 
584  ...
585  PString arg;
586  new PThread3Arg<PString, int, int>(arg1, arg2, arg3, &GlobalFunction)
587  */
588 template<typename Arg1Type, typename Arg2Type, typename Arg3Type>
589 class PThread3Arg : public PThread
590 {
591  PCLASSINFO(PThread3Arg, PThread);
592  public:
593  typedef void (*FnType)(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3);
595  Arg1Type arg1,
596  Arg2Type arg2,
597  Arg3Type arg3,
598  FnType function,
599  bool autoDel = false,
600  const char * name = NULL,
602  ) : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread, priority, name)
603  , m_function(function)
604  , m_arg1(arg1)
605  , m_arg2(arg2)
606  , m_arg3(arg3)
607  {
608  PThread::Resume();
609  }
610 
611  virtual void Main()
612  {
613  (*m_function)(m_arg1, m_arg2, m_arg3);
614  }
615 
616  protected:
618  Arg1Type m_arg1;
619  Arg2Type m_arg2;
620  Arg2Type m_arg3;
621 };
622 
623 /*
624  This template automates calling a member function with no arguments within it's own thread.
625  It is used as follows:
626 
627  class Example {
628  public:
629  void Function()
630  {
631  }
632  };
633 
634  ...
635  Example ex;
636  new PThreadObj<Example>(ex, &Example::Function)
637  */
638 
639 template <typename ObjType>
640 class PThreadObj : public PThread
641 {
642  PCLASSINFO(PThreadObj, PThread);
643  public:
644  typedef void (ObjType::*ObjTypeFn)();
645 
647  ObjType & obj,
648  ObjTypeFn function,
649  bool autoDel = false,
650  const char * name = NULL,
652  ) : PThread(10000,
654  priority,
655  name)
656  , m_object(obj)
657  , m_function(function)
658  {
659  PThread::Resume();
660  }
661 
662  void Main()
663  {
664  (m_object.*m_function)();
665  }
666 
667  protected:
668  ObjType & m_object;
669  P_ALIGN_FIELD(ObjTypeFn,m_function,16);
670 };
671 
672 
673 /*
674  This template automates calling a member function with one argument within it's own thread.
675  It is used as follows:
676 
677  class Example {
678  public:
679  void Function(PString arg)
680  {
681  }
682  };
683 
684  ...
685  Example ex;
686  PString str;
687  new PThreadObj1Arg<Example>(ex, str, &Example::Function)
688  */
689 template <class ObjType, typename Arg1Type>
690 class PThreadObj1Arg : public PThread
691 {
692  PCLASSINFO(PThreadObj1Arg, PThread);
693  public:
694  typedef void (ObjType::*ObjTypeFn)(Arg1Type);
695 
697  ObjType & obj,
698  Arg1Type arg1,
699  ObjTypeFn function,
700  bool autoDel = false,
701  const char * name = NULL,
703  ) : PThread(10000,
705  priority,
706  name)
707  , m_object(obj)
708  , m_function(function)
709  , m_arg1(arg1)
710  {
711  PThread::Resume();
712  }
713 
714  void Main()
715  {
716  (m_object.*m_function)(m_arg1);
717  }
718 
719  protected:
720  ObjType & m_object;
721  P_ALIGN_FIELD(ObjTypeFn,m_function,16);
722  Arg1Type m_arg1;
723 };
724 
725 template <class ObjType, typename Arg1Type, typename Arg2Type>
726 class PThreadObj2Arg : public PThread
727 {
728  PCLASSINFO(PThreadObj2Arg, PThread);
729  public:
730  typedef void (ObjType::*ObjTypeFn)(Arg1Type, Arg2Type);
731 
733  ObjType & obj,
734  Arg1Type arg1,
735  Arg2Type arg2,
736  ObjTypeFn function,
737  bool autoDel = false,
738  const char * name = NULL,
740  ) : PThread(10000,
742  priority,
743  name)
744  , m_object(obj)
745  , m_function(function)
746  , m_arg1(arg1)
747  , m_arg2(arg2)
748  {
749  PThread::Resume();
750  }
751 
752  void Main()
753  {
754  (m_object.*m_function)(m_arg1, m_arg2);
755  }
756 
757  protected:
758  ObjType & m_object;
759  P_ALIGN_FIELD(ObjTypeFn,m_function,16);
760  Arg1Type m_arg1;
761  Arg2Type m_arg2;
762 };
763 
764 
766 //
767 // PThreadLocalStorage
768 //
769 
770 template <class Storage_T>
772 {
773  public:
774  typedef Storage_T * Ptr_T;
775 
777  Ptr_T Get() const { return (Ptr_T)this->GetStorage(); }
778  operator Ptr_T() const { return (Ptr_T)this->GetStorage(); }
779  Ptr_T operator->() const { return (Ptr_T)this->GetStorage(); }
780  Storage_T & operator*() const { return *(Ptr_T)this->GetStorage(); }
781 
782  protected:
783  virtual void * Allocate() const { return new Storage_T(); }
784  virtual void Deallocate(void * ptr) const { delete (Ptr_T)ptr; }
785 };
786 
787 
788 #define P_HAS_THREADLOCAL_STORAGE 1 // For backward compatbility
789 
790 
791 #endif // PTLIB_THREAD_H
792 
793 // End Of File ///////////////////////////////////////////////////////////////