Blaze 3.9
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 <memory>
45#include <vector>
46#include <blaze/util/Assert.h>
50#include <blaze/util/Thread.h>
53#include <blaze/util/Types.h>
54
55
56namespace blaze {
57
58//=================================================================================================
59//
60// CLASS DEFINITION
61//
62//=================================================================================================
63
64//*************************************************************************************************
307template< typename TT // Type of the encapsulated thread
308 , typename MT // Type of the synchronization mutex
309 , typename LT // Type of the mutex lock
310 , typename CT > // Type of the condition variable
312 : private NonCopyable
313{
314 private:
315 //**Type definitions****************************************************************************
318
320 using Threads = std::vector< std::unique_ptr<ManagedThread> >;
321
323 using Mutex = MT;
324 using Lock = LT;
325 using Condition = CT;
326 //**********************************************************************************************
327
328 public:
329 //**Constructor*********************************************************************************
332 explicit ThreadPool( size_t n );
334 //**********************************************************************************************
335
336 //**Destructor**********************************************************************************
339 ~ThreadPool();
341 //**********************************************************************************************
342
343 //**Get functions*******************************************************************************
346 inline bool isEmpty() const;
347 inline size_t size() const;
348 inline size_t active() const;
349 inline size_t ready() const;
351 //**********************************************************************************************
352
353 //**Task scheduling*****************************************************************************
356 template< typename Callable, typename... Args >
357 void schedule( Callable func, Args&&... args );
359 //**********************************************************************************************
360
361 //**Utility functions***************************************************************************
364 void resize( size_t n, bool block=false );
365 void wait();
366 void clear();
368 //**********************************************************************************************
369
370 private:
371 //**Thread functions****************************************************************************
374 void createThread();
375 bool executeTask();
377 //**********************************************************************************************
378
379 //**Member variables****************************************************************************
382 volatile size_t total_;
383 volatile size_t expected_;
386 volatile size_t active_;
389 mutable Mutex mutex_;
393 //**********************************************************************************************
394
395 //**Friend declarations*************************************************************************
397 friend class Thread<TT,MT,LT,CT>;
399 //**********************************************************************************************
400};
401//*************************************************************************************************
402
403
404
405
406//=================================================================================================
407//
408// CONSTRUCTOR
409//
410//=================================================================================================
411
412//*************************************************************************************************
420template< typename TT // Type of the encapsulated thread
421 , typename MT // Type of the synchronization mutex
422 , typename LT // Type of the mutex lock
423 , typename CT > // Type of the condition variable
425 : total_ ( 0UL ) // Total number of threads in the thread pool
426 , expected_( 0UL ) // Expected number of threads in the thread pool
427 , active_ ( 0UL ) // Number of currently active/busy threads
428 , threads_ () // The threads contained in the thread pool
429 , taskqueue_ () // Task queue for the scheduled tasks
430 , mutex_ () // Synchronization mutex
431 , waitForTask_ () // Wait condition for idle threads
432 , waitForThread_() // Wait condition for the thread management
433{
434 resize( n );
435}
436//*************************************************************************************************
437
438
439
440
441//=================================================================================================
442//
443// DESTRUCTOR
444//
445//=================================================================================================
446
447//*************************************************************************************************
453template< typename TT // Type of the encapsulated thread
454 , typename MT // Type of the synchronization mutex
455 , typename LT // Type of the mutex lock
456 , typename CT > // Type of the condition variable
458{
459 Lock lock( mutex_ );
460
461 // Removing all currently queued tasks
462 taskqueue_.clear();
463
464 // Setting the expected number of threads
465 expected_ = 0UL;
466
467 // Notifying all idle threads
468 waitForTask_.notify_all();
469
470 // Waiting for all threads to terminate
471 while( total_ != 0UL ) {
472 waitForThread_.wait( lock );
473 }
474
475 // Joining all threads
476 for( auto const& thread : threads_ ) {
477 thread->join();
478 }
479
480 // Destroying all threads
481 threads_.clear();
482}
483//*************************************************************************************************
484
485
486
487
488//=================================================================================================
489//
490// GET FUNCTIONS
491//
492//=================================================================================================
493
494//*************************************************************************************************
499template< typename TT // Type of the encapsulated thread
500 , typename MT // Type of the synchronization mutex
501 , typename LT // Type of the mutex lock
502 , typename CT > // Type of the condition variable
504{
505 Lock lock( mutex_ );
506 return taskqueue_.isEmpty();
507}
508//*************************************************************************************************
509
510
511//*************************************************************************************************
516template< typename TT // Type of the encapsulated thread
517 , typename MT // Type of the synchronization mutex
518 , typename LT // Type of the mutex lock
519 , typename CT > // Type of the condition variable
520inline size_t ThreadPool<TT,MT,LT,CT>::size() const
521{
522 Lock lock( mutex_ );
523 return expected_;
524}
525//*************************************************************************************************
526
527
528//*************************************************************************************************
533template< typename TT // Type of the encapsulated thread
534 , typename MT // Type of the synchronization mutex
535 , typename LT // Type of the mutex lock
536 , typename CT > // Type of the condition variable
538{
539 Lock lock( mutex_ );
540 return active_;
541}
542//*************************************************************************************************
543
544
545//*************************************************************************************************
550template< typename TT // Type of the encapsulated thread
551 , typename MT // Type of the synchronization mutex
552 , typename LT // Type of the mutex lock
553 , typename CT > // Type of the condition variable
555{
556 Lock lock( mutex_ );
557 return expected_ - active_;
558}
559//*************************************************************************************************
560
561
562
563
564//=================================================================================================
565//
566// SCHEDULING FUNCTIONS
567//
568//=================================================================================================
569
570//*************************************************************************************************
581template< typename TT // Type of the encapsulated thread
582 , typename MT // Type of the synchronization mutex
583 , typename LT // Type of the mutex lock
584 , typename CT > // Type of the condition variable
585template< typename Callable // Type of the function/functor
586 , typename... Args > // Types of the function/functor arguments
587void ThreadPool<TT,MT,LT,CT>::schedule( Callable func, Args&&... args )
588{
589 Lock lock( mutex_ );
590 taskqueue_.push( std::bind<void>( func, std::forward<Args>( args )... ) );
591 waitForTask_.notify_one();
592}
593//*************************************************************************************************
594
595
596
597
598//=================================================================================================
599//
600// UTILITY FUNCTIONS
601//
602//=================================================================================================
603
604//*************************************************************************************************
644template< typename TT // Type of the encapsulated thread
645 , typename MT // Type of the synchronization mutex
646 , typename LT // Type of the mutex lock
647 , typename CT > // Type of the condition variable
648void ThreadPool<TT,MT,LT,CT>::resize( size_t n, bool block )
649{
650 // Checking the given number of threads
651#if !(defined _MSC_VER)
652 if( n == 0UL ) {
653 BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of threads" );
654 }
655#endif
656
657 // Adjusting the number of threads
658 {
659 Lock lock( mutex_ );
660
661 // Adding new threads to the thread pool
662 if( n > expected_ ) {
663 for( size_t i=expected_; i<n; ++i )
664 createThread();
665 }
666
667 // Removing threads from the pool
668 else {
669 expected_ = n;
670 waitForTask_.notify_all();
671
672 while( block && total_ != expected_ ) {
673 waitForThread_.wait( lock );
674 }
675 }
676
677 // Joining and destroying any terminated thread
678 for( typename Threads::iterator thread=threads_.begin(); thread!=threads_.end(); ) {
679 if( (*thread)->hasTerminated() ) {
680 (*thread)->join();
681 thread = threads_.erase( thread );
682 }
683 else ++thread;
684 }
685 }
686}
687//*************************************************************************************************
688
689
690//*************************************************************************************************
697template< typename TT // Type of the encapsulated thread
698 , typename MT // Type of the synchronization mutex
699 , typename LT // Type of the mutex lock
700 , typename CT > // Type of the condition variable
702{
703 Lock lock( mutex_ );
704
705 while( !taskqueue_.isEmpty() || active_ > 0UL ) {
706 waitForThread_.wait( lock );
707 }
708}
709//*************************************************************************************************
710
711
712//*************************************************************************************************
720template< typename TT // Type of the encapsulated thread
721 , typename MT // Type of the synchronization mutex
722 , typename LT // Type of the mutex lock
723 , typename CT > // Type of the condition variable
725{
726 Lock lock( mutex_ );
727 taskqueue_.clear();
728}
729//*************************************************************************************************
730
731
732
733
734//=================================================================================================
735//
736// THREAD FUNCTIONS
737//
738//=================================================================================================
739
740//*************************************************************************************************
745template< typename TT // Type of the encapsulated thread
746 , typename MT // Type of the synchronization mutex
747 , typename LT // Type of the mutex lock
748 , typename CT > // Type of the condition variable
750{
751 threads_.push_back( std::unique_ptr<ManagedThread>( new ManagedThread( this ) ) );
752 ++total_;
753 ++expected_;
754 ++active_;
755}
756//*************************************************************************************************
757
758
759//*************************************************************************************************
768template< typename TT // Type of the encapsulated thread
769 , typename MT // Type of the synchronization mutex
770 , typename LT // Type of the mutex lock
771 , typename CT > // Type of the condition variable
773{
774 threadpool::Task task;
775
776 // Acquiring a scheduled task
777 {
778 Lock lock( mutex_ );
779
780 while( taskqueue_.isEmpty() )
781 {
782 --active_;
783 waitForThread_.notify_all();
784
785 if( total_ > expected_ ) {
786 --total_;
787 return false;
788 }
789
790 waitForTask_.wait( lock );
791 ++active_;
792 }
793
794 BLAZE_INTERNAL_ASSERT( !taskqueue_.isEmpty(), "Empty task queue detected" );
795 task = taskqueue_.pop();
796 }
797
798 // Executing the task
799 task();
800
801 return true;
802}
803//*************************************************************************************************
804
805} // namespace blaze
806
807#endif
Header file for run time assertion macros.
Base class for non-copyable class instances.
Compile time assertion.
Task queue for the thread pool.
Header file for the Task base class.
Header file for the Thread class.
Base class for non-copyable class instances.
Definition: NonCopyable.h:64
Implementation of a thread pool.
Definition: ThreadPool.h:313
size_t ready() const
Returns the number of currently ready/inactive threads.
Definition: ThreadPool.h:554
void clear()
Removing all scheduled tasks from the thread pool.
Definition: ThreadPool.h:724
Threads threads_
The threads contained in the thread pool.
Definition: ThreadPool.h:387
volatile size_t expected_
Expected number of threads in the thread pool.
Definition: ThreadPool.h:383
Condition waitForThread_
Wait condition for the thread management.
Definition: ThreadPool.h:391
MT Mutex
Type of the mutex.
Definition: ThreadPool.h:323
void schedule(Callable func, Args &&... args)
Scheduling the given function/functor for execution.
Definition: ThreadPool.h:587
void resize(size_t n, bool block=false)
Changes the total number of threads in the thread pool.
Definition: ThreadPool.h:648
void createThread()
Adding a new thread to the thread pool.
Definition: ThreadPool.h:749
CT Condition
Condition variable type.
Definition: ThreadPool.h:325
Mutex mutex_
Synchronization mutex.
Definition: ThreadPool.h:389
ThreadPool(size_t n)
Constructor for the ThreadPool class.
Definition: ThreadPool.h:424
size_t active() const
Returns the number of currently active/busy threads.
Definition: ThreadPool.h:537
std::vector< std::unique_ptr< ManagedThread > > Threads
Type of the thread container.
Definition: ThreadPool.h:320
volatile size_t total_
Total number of threads in the thread pool.
Definition: ThreadPool.h:382
~ThreadPool()
Destructor for the ThreadPool class.
Definition: ThreadPool.h:457
LT Lock
Type of a locking object.
Definition: ThreadPool.h:324
TaskQueue taskqueue_
Task queue for the scheduled tasks.
Definition: ThreadPool.h:388
bool executeTask()
Executing a scheduled task.
Definition: ThreadPool.h:772
bool isEmpty() const
Returns whether any tasks are scheduled for execution.
Definition: ThreadPool.h:503
void wait()
Waiting for all scheduled tasks to be completed.
Definition: ThreadPool.h:701
Condition waitForTask_
Wait condition for idle threads.
Definition: ThreadPool.h:390
size_t size() const
Returns the current size of the thread pool.
Definition: ThreadPool.h:520
volatile size_t active_
Number of currently active/busy threads.
Definition: ThreadPool.h:386
Implementation of a single thread of execution.
Definition: Thread.h:252
Task queue for the thread pool.
Definition: TaskQueue.h:65
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.
Definition: Assert.h:101
std::function< void(void)> Task
Handle for a single, executable task.
Definition: Task.h:60
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.
Definition: Exception.h:235
Header file for exception macros.
Header file for basic type definitions.