ThreadPool.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
36 #define _BLAZE_UTIL_THREADPOOL_THREADPOOL_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <boost/bind.hpp>
44 #include <blaze/util/Assert.h>
45 #include <blaze/util/Exception.h>
46 #include <blaze/util/NonCopyable.h>
47 #include <blaze/util/PtrVector.h>
49 #include <blaze/util/Thread.h>
52 #include <blaze/util/Types.h>
53 
54 
55 namespace blaze {
56 
57 //=================================================================================================
58 //
59 // CLASS DEFINITION
60 //
61 //=================================================================================================
62 
63 //*************************************************************************************************
306 template< typename TT // Type of the encapsulated thread
307  , typename MT // Type of the synchronization mutex
308  , typename LT // Type of the mutex lock
309  , typename CT > // Type of the condition variable
310 class ThreadPool : private NonCopyable
311 {
312  private:
313  //**Type definitions****************************************************************************
317  typedef MT Mutex;
318  typedef LT Lock;
319  typedef CT Condition;
320  //**********************************************************************************************
321 
322  public:
323  //**Constructor*********************************************************************************
326  explicit ThreadPool( size_t n );
328  //**********************************************************************************************
329 
330  //**Destructor**********************************************************************************
333  ~ThreadPool();
335  //**********************************************************************************************
336 
337  //**Get functions*******************************************************************************
340  inline bool isEmpty() const;
341  inline size_t size() const;
342  inline size_t active() const;
343  inline size_t ready() const;
345  //**********************************************************************************************
346 
347  //**Scheduling functions************************************************************************
350  template< typename Callable >
351  void schedule( Callable func );
352 
353  template< typename Callable, typename A1 >
354  void schedule( Callable func, A1 a1 );
355 
356  template< typename Callable, typename A1, typename A2 >
357  void schedule( Callable func, A1 a1, A2 a2 );
358 
359  template< typename Callable, typename A1, typename A2, typename A3 >
360  void schedule( Callable func, A1 a1, A2 a2, A3 a3 );
361 
362  template< typename Callable, typename A1, typename A2, typename A3, typename A4 >
363  void schedule( Callable func, A1 a1, A2 a2, A3 a3, A4 a4 );
364 
365  template< typename Callable, typename A1, typename A2, typename A3, typename A4, typename A5 >
366  void schedule( Callable func, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 );
368  //**********************************************************************************************
369 
370  //**Utility functions***************************************************************************
373  void resize( size_t n, bool block=false );
374  void wait();
375  void clear();
377  //**********************************************************************************************
378 
379  private:
380  //**Thread functions****************************************************************************
383  void createThread();
384  bool executeTask();
386  //**********************************************************************************************
387 
388  //**Member variables****************************************************************************
391  volatile size_t total_;
392  volatile size_t expected_;
393 
395  volatile size_t active_;
396  Threads threads_;
397  TaskQueue taskqueue_;
398  mutable Mutex mutex_;
399  Condition waitForTask_;
400  Condition waitForThread_;
401 
402  //**********************************************************************************************
403 
404  //**Friend declarations*************************************************************************
406  friend class Thread<TT,MT,LT,CT>;
408  //**********************************************************************************************
409 };
410 //*************************************************************************************************
411 
412 
413 
414 
415 //=================================================================================================
416 //
417 // CONSTRUCTOR
418 //
419 //=================================================================================================
420 
421 //*************************************************************************************************
429 template< typename TT // Type of the encapsulated thread
430  , typename MT // Type of the synchronization mutex
431  , typename LT // Type of the mutex lock
432  , typename CT > // Type of the condition variable
434  : total_ ( 0 ) // Total number of threads in the thread pool
435  , expected_ ( 0 ) // Expected number of threads in the thread pool
436  , active_ ( 0 ) // Number of currently active/busy threads
437  , threads_ () // The threads contained in the thread pool
438  , taskqueue_ () // Task queue for the scheduled tasks
439  , mutex_ () // Synchronization mutex
440  , waitForTask_ () // Wait condition for idle threads
441  , waitForThread_() // Wait condition for the thread management
442 {
443  resize( n );
444 }
445 //*************************************************************************************************
446 
447 
448 
449 
450 //=================================================================================================
451 //
452 // DESTRUCTOR
453 //
454 //=================================================================================================
455 
456 //*************************************************************************************************
462 template< typename TT // Type of the encapsulated thread
463  , typename MT // Type of the synchronization mutex
464  , typename LT // Type of the mutex lock
465  , typename CT > // Type of the condition variable
467 {
468  Lock lock( mutex_ );
469 
470  // Removing all currently queued tasks
471  taskqueue_.clear();
472 
473  // Setting the expected number of threads
474  expected_ = 0;
475 
476  // Notifying all idle threads
477  waitForTask_.notify_all();
478 
479  // Waiting for all threads to terminate
480  while( total_ != 0 ) {
481  waitForThread_.wait( lock );
482  }
483 
484  // Joining all threads
485  for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ++thread ) {
486  thread->join();
487  }
488 
489  // Destroying all threads
490  threads_.clear();
491 }
492 //*************************************************************************************************
493 
494 
495 
496 
497 //=================================================================================================
498 //
499 // GET FUNCTIONS
500 //
501 //=================================================================================================
502 
503 //*************************************************************************************************
508 template< typename TT // Type of the encapsulated thread
509  , typename MT // Type of the synchronization mutex
510  , typename LT // Type of the mutex lock
511  , typename CT > // Type of the condition variable
513 {
514  Lock lock( mutex_ );
515  return taskqueue_.isEmpty();
516 }
517 //*************************************************************************************************
518 
519 
520 //*************************************************************************************************
525 template< typename TT // Type of the encapsulated thread
526  , typename MT // Type of the synchronization mutex
527  , typename LT // Type of the mutex lock
528  , typename CT > // Type of the condition variable
529 inline size_t ThreadPool<TT,MT,LT,CT>::size() const
530 {
531  Lock lock( mutex_ );
532  return expected_;
533 }
534 //*************************************************************************************************
535 
536 
537 //*************************************************************************************************
542 template< typename TT // Type of the encapsulated thread
543  , typename MT // Type of the synchronization mutex
544  , typename LT // Type of the mutex lock
545  , typename CT > // Type of the condition variable
546 inline size_t ThreadPool<TT,MT,LT,CT>::active() const
547 {
548  Lock lock( mutex_ );
549  return active_;
550 }
551 //*************************************************************************************************
552 
553 
554 //*************************************************************************************************
559 template< typename TT // Type of the encapsulated thread
560  , typename MT // Type of the synchronization mutex
561  , typename LT // Type of the mutex lock
562  , typename CT > // Type of the condition variable
563 inline size_t ThreadPool<TT,MT,LT,CT>::ready() const
564 {
565  Lock lock( mutex_ );
566  return expected_ - active_;
567 }
568 //*************************************************************************************************
569 
570 
571 
572 
573 //=================================================================================================
574 //
575 // SCHEDULING FUNCTIONS
576 //
577 //=================================================================================================
578 
579 //*************************************************************************************************
588 template< typename TT // Type of the encapsulated thread
589  , typename MT // Type of the synchronization mutex
590  , typename LT // Type of the mutex lock
591  , typename CT > // Type of the condition variable
592 template< typename Callable > // Type of the function/functor
594 {
595  Lock lock( mutex_ );
596  taskqueue_.push( func );
597  waitForTask_.notify_one();
598 }
599 //*************************************************************************************************
600 
601 
602 //*************************************************************************************************
612 template< typename TT // Type of the encapsulated thread
613  , typename MT // Type of the synchronization mutex
614  , typename LT // Type of the mutex lock
615  , typename CT > // Type of the condition variable
616 template< typename Callable // Type of the function/functor
617  , typename A1 > // Type of the first argument
618 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, A1 a1 )
619 {
620  Lock lock( mutex_ );
621  taskqueue_.push( boost::bind<void>( func, a1 ) );
622  waitForTask_.notify_one();
623 }
624 //*************************************************************************************************
625 
626 
627 //*************************************************************************************************
638 template< typename TT // Type of the encapsulated thread
639  , typename MT // Type of the synchronization mutex
640  , typename LT // Type of the mutex lock
641  , typename CT > // Type of the condition variable
642 template< typename Callable // Type of the function/functor
643  , typename A1 // Type of the first argument
644  , typename A2 > // Type of the second argument
645 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, A1 a1, A2 a2 )
646 {
647  Lock lock( mutex_ );
648  taskqueue_.push( boost::bind<void>( func, a1, a2 ) );
649  waitForTask_.notify_one();
650 }
651 //*************************************************************************************************
652 
653 
654 //*************************************************************************************************
666 template< typename TT // Type of the encapsulated thread
667  , typename MT // Type of the synchronization mutex
668  , typename LT // Type of the mutex lock
669  , typename CT > // Type of the condition variable
670 template< typename Callable // Type of the function/functor
671  , typename A1 // Type of the first argument
672  , typename A2 // Type of the second argument
673  , typename A3 > // Type of the third argument
674 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, A1 a1, A2 a2, A3 a3 )
675 {
676  Lock lock( mutex_ );
677  taskqueue_.push( boost::bind<void>( func, a1, a2, a3 ) );
678  waitForTask_.notify_one();
679 }
680 //*************************************************************************************************
681 
682 
683 //*************************************************************************************************
696 template< typename TT // Type of the encapsulated thread
697  , typename MT // Type of the synchronization mutex
698  , typename LT // Type of the mutex lock
699  , typename CT > // Type of the condition variable
700 template< typename Callable // Type of the function/functor
701  , typename A1 // Type of the first argument
702  , typename A2 // Type of the second argument
703  , typename A3 // Type of the third argument
704  , typename A4 > // Type of the fourth argument
705 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, A1 a1, A2 a2, A3 a3, A4 a4 )
706 {
707  Lock lock( mutex_ );
708  taskqueue_.push( boost::bind<void>( func, a1, a2, a3, a4 ) );
709  waitForTask_.notify_one();
710 }
711 //*************************************************************************************************
712 
713 
714 //*************************************************************************************************
728 template< typename TT // Type of the encapsulated thread
729  , typename MT // Type of the synchronization mutex
730  , typename LT // Type of the mutex lock
731  , typename CT > // Type of the condition variable
732 template< typename Callable // Type of the function/functor
733  , typename A1 // Type of the first argument
734  , typename A2 // Type of the second argument
735  , typename A3 // Type of the third argument
736  , typename A4 // Type of the fourth argument
737  , typename A5 > // Type of the fifth argument
738 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5 )
739 {
740  Lock lock( mutex_ );
741  taskqueue_.push( boost::bind<void>( func, a1, a2, a3, a4, a5 ) );
742  waitForTask_.notify_one();
743 }
744 //*************************************************************************************************
745 
746 
747 
748 
749 //=================================================================================================
750 //
751 // UTILITY FUNCTIONS
752 //
753 //=================================================================================================
754 
755 //*************************************************************************************************
795 template< typename TT // Type of the encapsulated thread
796  , typename MT // Type of the synchronization mutex
797  , typename LT // Type of the mutex lock
798  , typename CT > // Type of the condition variable
799 void ThreadPool<TT,MT,LT,CT>::resize( size_t n, bool block )
800 {
801  // Checking the given number of threads
802 #if !(defined _MSC_VER)
803  if( n == 0 ) {
804  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
805  }
806 #endif
807 
808  // Adjusting the number of threads
809  {
810  Lock lock( mutex_ );
811 
812  // Adding new threads to the thread pool
813  if( n > expected_ ) {
814  for( size_t i=expected_; i<n; ++i )
815  createThread();
816  }
817 
818  // Removing threads from the pool
819  else {
820  expected_ = n;
821  waitForTask_.notify_all();
822 
823  while( block && total_ != expected_ ) {
824  waitForThread_.wait( lock );
825  }
826  }
827 
828  // Joining and destroying any terminated thread
829  for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ) {
830  if( thread->hasTerminated() ) {
831  thread->join();
832  thread = threads_.erase( thread );
833  }
834  else ++thread;
835  }
836  }
837 }
838 //*************************************************************************************************
839 
840 
841 //*************************************************************************************************
848 template< typename TT // Type of the encapsulated thread
849  , typename MT // Type of the synchronization mutex
850  , typename LT // Type of the mutex lock
851  , typename CT > // Type of the condition variable
853 {
854  Lock lock( mutex_ );
855 
856  while( !taskqueue_.isEmpty() || active_ > 0 ) {
857  waitForThread_.wait( lock );
858  }
859 }
860 //*************************************************************************************************
861 
862 
863 //*************************************************************************************************
871 template< typename TT // Type of the encapsulated thread
872  , typename MT // Type of the synchronization mutex
873  , typename LT // Type of the mutex lock
874  , typename CT > // Type of the condition variable
876 {
877  Lock lock( mutex_ );
878  taskqueue_.clear();
879 }
880 //*************************************************************************************************
881 
882 
883 
884 
885 //=================================================================================================
886 //
887 // THREAD FUNCTIONS
888 //
889 //=================================================================================================
890 
891 //*************************************************************************************************
896 template< typename TT // Type of the encapsulated thread
897  , typename MT // Type of the synchronization mutex
898  , typename LT // Type of the mutex lock
899  , typename CT > // Type of the condition variable
901 {
902  threads_.pushBack( new ManagedThread( this ) );
903  ++total_;
904  ++expected_;
905  ++active_;
906 }
907 //*************************************************************************************************
908 
909 
910 //*************************************************************************************************
919 template< typename TT // Type of the encapsulated thread
920  , typename MT // Type of the synchronization mutex
921  , typename LT // Type of the mutex lock
922  , typename CT > // Type of the condition variable
924 {
925  threadpool::Task task;
926 
927  // Acquiring a scheduled task
928  {
929  Lock lock( mutex_ );
930 
931  while( taskqueue_.isEmpty() )
932  {
933  --active_;
934  waitForThread_.notify_all();
935 
936  if( total_ > expected_ ) {
937  --total_;
938  return false;
939  }
940 
941  waitForTask_.wait( lock );
942  ++active_;
943  }
944 
945  BLAZE_INTERNAL_ASSERT( !taskqueue_.isEmpty(), "Empty task queue detected" );
946  task = taskqueue_.pop();
947  }
948 
949  // Executing the task
950  task();
951 
952  return true;
953 }
954 //*************************************************************************************************
955 
956 } // namespace blaze
957 
958 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exceptionThis macro encapsulates the default way of...
Definition: Exception.h:187
size_t size() const
Returns the current size of the thread pool.
Definition: ThreadPool.h:529
Thread< TT, MT, LT, CT > ManagedThread
Type of the managed threads.
Definition: ThreadPool.h:314
void schedule(Callable func)
Scheduling the given zero argument function/functor for execution.
Definition: ThreadPool.h:593
Header file for basic type definitions.
Condition waitForTask_
Wait condition for idle threads.
Definition: ThreadPool.h:399
void clear()
Removing all scheduled tasks from the thread pool.
Definition: ThreadPool.h:875
Base class for non-copyable class instances.
void createThread()
Adding a new thread to the thread pool.
Definition: ThreadPool.h:900
Mutex mutex_
Synchronization mutex.
Definition: ThreadPool.h:398
void resize(size_t n, bool block=false)
Changes the total number of threads in the thread pool.
Definition: ThreadPool.h:799
size_t active() const
Returns the number of currently active/busy threads.
Definition: ThreadPool.h:546
volatile size_t active_
Number of currently active/busy threads.
Definition: ThreadPool.h:395
bool executeTask()
Executing a scheduled task.
Definition: ThreadPool.h:923
LT Lock
Type of a locking object.
Definition: ThreadPool.h:318
Implementation of a vector for (polymorphic) pointers.
volatile size_t expected_
Expected number of threads in the thread pool.
Definition: ThreadPool.h:392
Task queue for the thread pool.
~ThreadPool()
Destructor for the ThreadPool class.
Definition: ThreadPool.h:466
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
Compile time assertion.
Header file for the Thread class.
Condition waitForThread_
Wait condition for the thread management.
Definition: ThreadPool.h:400
bool isEmpty() const
Returns whether any tasks are scheduled for execution.
Definition: ThreadPool.h:512
Implementation of a single thread of execution.
Definition: Thread.h:250
Implementation of an iterator for pointer vectors.The PtrIterator class follows the example of the ra...
Definition: PtrIterator.h:108
MT Mutex
Type of the mutex.
Definition: ThreadPool.h:317
ThreadPool(size_t n)
Constructor for the ThreadPool class.
Definition: ThreadPool.h:433
PtrVector< ManagedThread > Threads
Type of the thread container.
Definition: ThreadPool.h:315
Header file for run time assertion macros.
Threads threads_
The threads contained in the thread pool.
Definition: ThreadPool.h:396
threadpool::TaskQueue TaskQueue
Type of the task queue.
Definition: ThreadPool.h:316
Header file for the Task base class.
boost::function< void(void)> Task
Handle for a single, executable task.
Definition: Task.h:60
void wait()
Waiting for all scheduled tasks to be completed.
Definition: ThreadPool.h:852
volatile size_t total_
Total number of threads in the thread pool.
Definition: ThreadPool.h:391
Task queue for the thread pool.The TaskQueue class represents the internal task container of a thread...
Definition: TaskQueue.h:64
size_t ready() const
Returns the number of currently ready/inactive threads.
Definition: ThreadPool.h:563
TaskQueue taskqueue_
Task queue for the scheduled tasks.
Definition: ThreadPool.h:397
Header file for exception macros.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
CT Condition
Condition variable type.
Definition: ThreadPool.h:319