PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

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: 30585 $
30 * $Author: rjongbloed $
31 * $Date: 2013-09-30 16:51:43 +1000 (Mon, 30 Sep 2013) $
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 {
77 LowestPriority,
78
79 LowPriority,
80
81 NormalPriority,
82
83 HighPriority,
84
85 HighestPriority,
86
87 NumPriorities
88 };
89
91 enum AutoDeleteFlag {
93 AutoDeleteThread,
94
96 NoAutoDeleteThread
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
187 PBoolean WaitForTermination(
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
266 void SetNoAutoDelete() { SetAutoDelete(NoAutoDeleteThread); }
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 {
298 PTimeInterval m_real;
299 PTimeInterval m_kernel;
300 PTimeInterval m_user;
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
360 class LocalStorageBase
361 {
362 public:
363 virtual ~LocalStorageBase() { }
364 protected:
365 LocalStorageBase() { }
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:
396 enum Type { e_IsAutoDelete, e_IsManualDelete, e_IsProcess, e_IsExternal } m_type;
397
398 PINDEX m_originalStackSize;
399
400 PString m_threadName; // Give the thread a name for debugging purposes.
401 PMutex m_threadNameMutex;
402
403 PThreadIdentifier m_threadId;
404
405 typedef std::list<const LocalStorageBase *> LocalStorageList;
406 LocalStorageList m_localStorage;
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)
439 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
440 , m_function(function)
441 {
442 PThread::Resume();
443 }
444
445 virtual void Main()
446 {
447 (*m_function)();
448 }
449
450 protected:
451 FnType m_function;
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)
473 : PThread(10000, autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread)
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
508 PThread1Arg(
509 Arg1Type arg1,
510 FnType function,
511 bool autoDel = false,
512 const char * name = NULL,
513 PThread::Priority priority = PThread::NormalPriority
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:
527 FnType m_function;
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);
550 PThread2Arg(
551 Arg1Type arg1,
552 Arg2Type arg2,
553 FnType function,
554 bool autoDel = false,
555 const char * name = NULL,
556 PThread::Priority priority = PThread::NormalPriority
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:
571 FnType m_function;
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);
594 PThread3Arg(
595 Arg1Type arg1,
596 Arg2Type arg2,
597 Arg3Type arg3,
598 FnType function,
599 bool autoDel = false,
600 const char * name = NULL,
601 PThread::Priority priority = PThread::NormalPriority
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:
617 FnType m_function;
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
646 PThreadObj(
647 ObjType & obj,
648 ObjTypeFn function,
649 bool autoDel = false,
650 const char * name = NULL,
651 PThread::Priority priority = PThread::NormalPriority
652 ) : PThread(10000,
653 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
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 ObjTypeFn P_ALIGN_FIELD(m_function, 8);
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
696 PThreadObj1Arg(
697 ObjType & obj,
698 Arg1Type arg1,
699 ObjTypeFn function,
700 bool autoDel = false,
701 const char * name = NULL,
702 PThread::Priority priority = PThread::NormalPriority
703 ) : PThread(10000,
704 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
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 ObjTypeFn P_ALIGN_FIELD(m_function, 8);
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
732 PThreadObj2Arg(
733 ObjType & obj,
734 Arg1Type arg1,
735 Arg2Type arg2,
736 ObjTypeFn function,
737 bool autoDel = false,
738 const char * name = NULL,
739 PThread::Priority priority = PThread::NormalPriority
740 ) : PThread(10000,
741 autoDel ? PThread::AutoDeleteThread : PThread::NoAutoDeleteThread,
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 ObjTypeFn P_ALIGN_FIELD(m_function, 8);
760 Arg1Type m_arg1;
761 Arg2Type m_arg2;
762 };
763
764
766 //
767 // PThreadLocalStorage
768 //
769
770 template <class Storage_T>
771 class PThreadLocalStorage : public PThread::LocalStorageBase
772 {
773 public:
774 typedef Storage_T * Ptr_T;
775
776 ~PThreadLocalStorage() { this->StorageDestroyed(); }
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 ///////////////////////////////////////////////////////////////