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 <functional>
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  //**Task scheduling*****************************************************************************
350  template< typename Callable, typename... Args >
351  void schedule( Callable func, Args&&... args );
353  //**********************************************************************************************
354 
355  //**Utility functions***************************************************************************
358  void resize( size_t n, bool block=false );
359  void wait();
360  void clear();
362  //**********************************************************************************************
363 
364  private:
365  //**Thread functions****************************************************************************
368  void createThread();
369  bool executeTask();
371  //**********************************************************************************************
372 
373  //**Member variables****************************************************************************
376  volatile size_t total_;
377  volatile size_t expected_;
378 
380  volatile size_t active_;
381  Threads threads_;
382  TaskQueue taskqueue_;
383  mutable Mutex mutex_;
384  Condition waitForTask_;
385  Condition waitForThread_;
386 
387  //**********************************************************************************************
388 
389  //**Friend declarations*************************************************************************
391  friend class Thread<TT,MT,LT,CT>;
393  //**********************************************************************************************
394 };
395 //*************************************************************************************************
396 
397 
398 
399 
400 //=================================================================================================
401 //
402 // CONSTRUCTOR
403 //
404 //=================================================================================================
405 
406 //*************************************************************************************************
414 template< typename TT // Type of the encapsulated thread
415  , typename MT // Type of the synchronization mutex
416  , typename LT // Type of the mutex lock
417  , typename CT > // Type of the condition variable
419  : total_ ( 0UL ) // Total number of threads in the thread pool
420  , expected_( 0UL ) // Expected number of threads in the thread pool
421  , active_ ( 0UL ) // Number of currently active/busy threads
422  , threads_ () // The threads contained in the thread pool
423  , taskqueue_ () // Task queue for the scheduled tasks
424  , mutex_ () // Synchronization mutex
425  , waitForTask_ () // Wait condition for idle threads
426  , waitForThread_() // Wait condition for the thread management
427 {
428  resize( n );
429 }
430 //*************************************************************************************************
431 
432 
433 
434 
435 //=================================================================================================
436 //
437 // DESTRUCTOR
438 //
439 //=================================================================================================
440 
441 //*************************************************************************************************
447 template< typename TT // Type of the encapsulated thread
448  , typename MT // Type of the synchronization mutex
449  , typename LT // Type of the mutex lock
450  , typename CT > // Type of the condition variable
452 {
453  Lock lock( mutex_ );
454 
455  // Removing all currently queued tasks
456  taskqueue_.clear();
457 
458  // Setting the expected number of threads
459  expected_ = 0UL;
460 
461  // Notifying all idle threads
462  waitForTask_.notify_all();
463 
464  // Waiting for all threads to terminate
465  while( total_ != 0UL ) {
466  waitForThread_.wait( lock );
467  }
468 
469  // Joining all threads
470  for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ++thread ) {
471  thread->join();
472  }
473 
474  // Destroying all threads
475  threads_.clear();
476 }
477 //*************************************************************************************************
478 
479 
480 
481 
482 //=================================================================================================
483 //
484 // GET FUNCTIONS
485 //
486 //=================================================================================================
487 
488 //*************************************************************************************************
493 template< typename TT // Type of the encapsulated thread
494  , typename MT // Type of the synchronization mutex
495  , typename LT // Type of the mutex lock
496  , typename CT > // Type of the condition variable
498 {
499  Lock lock( mutex_ );
500  return taskqueue_.isEmpty();
501 }
502 //*************************************************************************************************
503 
504 
505 //*************************************************************************************************
510 template< typename TT // Type of the encapsulated thread
511  , typename MT // Type of the synchronization mutex
512  , typename LT // Type of the mutex lock
513  , typename CT > // Type of the condition variable
514 inline size_t ThreadPool<TT,MT,LT,CT>::size() const
515 {
516  Lock lock( mutex_ );
517  return expected_;
518 }
519 //*************************************************************************************************
520 
521 
522 //*************************************************************************************************
527 template< typename TT // Type of the encapsulated thread
528  , typename MT // Type of the synchronization mutex
529  , typename LT // Type of the mutex lock
530  , typename CT > // Type of the condition variable
531 inline size_t ThreadPool<TT,MT,LT,CT>::active() const
532 {
533  Lock lock( mutex_ );
534  return active_;
535 }
536 //*************************************************************************************************
537 
538 
539 //*************************************************************************************************
544 template< typename TT // Type of the encapsulated thread
545  , typename MT // Type of the synchronization mutex
546  , typename LT // Type of the mutex lock
547  , typename CT > // Type of the condition variable
548 inline size_t ThreadPool<TT,MT,LT,CT>::ready() const
549 {
550  Lock lock( mutex_ );
551  return expected_ - active_;
552 }
553 //*************************************************************************************************
554 
555 
556 
557 
558 //=================================================================================================
559 //
560 // SCHEDULING FUNCTIONS
561 //
562 //=================================================================================================
563 
564 //*************************************************************************************************
575 template< typename TT // Type of the encapsulated thread
576  , typename MT // Type of the synchronization mutex
577  , typename LT // Type of the mutex lock
578  , typename CT > // Type of the condition variable
579 template< typename Callable // Type of the function/functor
580  , typename... Args > // Types of the function/functor arguments
581 void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, Args&&... args )
582 {
583  Lock lock( mutex_ );
584  taskqueue_.push( std::bind<void>( func, std::forward<Args>( args )... ) );
585  waitForTask_.notify_one();
586 }
587 //*************************************************************************************************
588 
589 
590 
591 
592 //=================================================================================================
593 //
594 // UTILITY FUNCTIONS
595 //
596 //=================================================================================================
597 
598 //*************************************************************************************************
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 void ThreadPool<TT,MT,LT,CT>::resize( size_t n, bool block )
643 {
644  // Checking the given number of threads
645 #if !(defined _MSC_VER)
646  if( n == 0UL ) {
647  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
648  }
649 #endif
650 
651  // Adjusting the number of threads
652  {
653  Lock lock( mutex_ );
654 
655  // Adding new threads to the thread pool
656  if( n > expected_ ) {
657  for( size_t i=expected_; i<n; ++i )
658  createThread();
659  }
660 
661  // Removing threads from the pool
662  else {
663  expected_ = n;
664  waitForTask_.notify_all();
665 
666  while( block && total_ != expected_ ) {
667  waitForThread_.wait( lock );
668  }
669  }
670 
671  // Joining and destroying any terminated thread
672  for( typename Threads::Iterator thread=threads_.begin(); thread!=threads_.end(); ) {
673  if( thread->hasTerminated() ) {
674  thread->join();
675  thread = threads_.erase( thread );
676  }
677  else ++thread;
678  }
679  }
680 }
681 //*************************************************************************************************
682 
683 
684 //*************************************************************************************************
691 template< typename TT // Type of the encapsulated thread
692  , typename MT // Type of the synchronization mutex
693  , typename LT // Type of the mutex lock
694  , typename CT > // Type of the condition variable
696 {
697  Lock lock( mutex_ );
698 
699  while( !taskqueue_.isEmpty() || active_ > 0UL ) {
700  waitForThread_.wait( lock );
701  }
702 }
703 //*************************************************************************************************
704 
705 
706 //*************************************************************************************************
714 template< typename TT // Type of the encapsulated thread
715  , typename MT // Type of the synchronization mutex
716  , typename LT // Type of the mutex lock
717  , typename CT > // Type of the condition variable
719 {
720  Lock lock( mutex_ );
721  taskqueue_.clear();
722 }
723 //*************************************************************************************************
724 
725 
726 
727 
728 //=================================================================================================
729 //
730 // THREAD FUNCTIONS
731 //
732 //=================================================================================================
733 
734 //*************************************************************************************************
739 template< typename TT // Type of the encapsulated thread
740  , typename MT // Type of the synchronization mutex
741  , typename LT // Type of the mutex lock
742  , typename CT > // Type of the condition variable
744 {
745  threads_.pushBack( new ManagedThread( this ) );
746  ++total_;
747  ++expected_;
748  ++active_;
749 }
750 //*************************************************************************************************
751 
752 
753 //*************************************************************************************************
762 template< typename TT // Type of the encapsulated thread
763  , typename MT // Type of the synchronization mutex
764  , typename LT // Type of the mutex lock
765  , typename CT > // Type of the condition variable
767 {
768  threadpool::Task task;
769 
770  // Acquiring a scheduled task
771  {
772  Lock lock( mutex_ );
773 
774  while( taskqueue_.isEmpty() )
775  {
776  --active_;
777  waitForThread_.notify_all();
778 
779  if( total_ > expected_ ) {
780  --total_;
781  return false;
782  }
783 
784  waitForTask_.wait( lock );
785  ++active_;
786  }
787 
788  BLAZE_INTERNAL_ASSERT( !taskqueue_.isEmpty(), "Empty task queue detected" );
789  task = taskqueue_.pop();
790  }
791 
792  // Executing the task
793  task();
794 
795  return true;
796 }
797 //*************************************************************************************************
798 
799 } // namespace blaze
800 
801 #endif
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
size_t size() const
Returns the current size of the thread pool.
Definition: ThreadPool.h:514
Thread< TT, MT, LT, CT > ManagedThread
Type of the managed threads.
Definition: ThreadPool.h:314
Header file for basic type definitions.
Condition waitForTask_
Wait condition for idle threads.
Definition: ThreadPool.h:384
void clear()
Removing all scheduled tasks from the thread pool.
Definition: ThreadPool.h:718
Header file for exception macros.
Base class for non-copyable class instances.
void createThread()
Adding a new thread to the thread pool.
Definition: ThreadPool.h:743
Mutex mutex_
Synchronization mutex.
Definition: ThreadPool.h:383
void resize(size_t n, bool block=false)
Changes the total number of threads in the thread pool.
Definition: ThreadPool.h:642
std::function< void(void)> Task
Handle for a single, executable task.
Definition: Task.h:60
size_t active() const
Returns the number of currently active/busy threads.
Definition: ThreadPool.h:531
volatile size_t active_
Number of currently active/busy threads.
Definition: ThreadPool.h:380
bool executeTask()
Executing a scheduled task.
Definition: ThreadPool.h:766
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:377
Task queue for the thread pool.
~ThreadPool()
Destructor for the ThreadPool class.
Definition: ThreadPool.h:451
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:385
bool isEmpty() const
Returns whether any tasks are scheduled for execution.
Definition: ThreadPool.h:497
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:107
MT Mutex
Type of the mutex.
Definition: ThreadPool.h:317
ThreadPool(size_t n)
Constructor for the ThreadPool class.
Definition: ThreadPool.h:418
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:381
threadpool::TaskQueue TaskQueue
Type of the task queue.
Definition: ThreadPool.h:316
Header file for the Task base class.
void wait()
Waiting for all scheduled tasks to be completed.
Definition: ThreadPool.h:695
volatile size_t total_
Total number of threads in the thread pool.
Definition: ThreadPool.h:376
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:548
TaskQueue taskqueue_
Task queue for the scheduled tasks.
Definition: ThreadPool.h:382
void schedule(Callable func, Args &&...args)
Scheduling the given function/functor for execution.
Definition: ThreadPool.h:581
#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