Threads Module User's Guide : PART II Concurrency Packages : Chapter 3 The Threading Package : The Thread Pool Class
The Thread Pool Class
A thread pool is a collection of RWThread instances that enqueue and execute work encapsulated as RWFunctor<void()> functors. (See Chapter 8, “The Functor Package,” for more information on functors.)
RWThreadPool is a high-performance alternative when you don't need all the functionality of the runnable server classes, such as RWServerPool.
Constructing a Thread Pool
To construct a thread pool, you must use one of the static make() functions provided by the thread pool handle class, RWThreadPool, as shown in Example 21.
Example 21 – Constructing a thread pool
// Make a thread pool of 10 threads.
RWThreadPool threadPool=RWThreadPool::make(10);
RWThreadPool’s static make() functions accept parameters detailing the minimum and maximum number of threads in the thread pool and how long a thread will remain in the pool waiting for work before it removes itself. Except for the minimum number of threads in the pool, all of the parameters are optional.
RWThreadPool::make() can also accept RWThreadAttribute instances that can be used to establish the initial attributes of any threads created by RWThreadPool. Please note that you are responsible for determining the suitability of thread pool attributes. For example, if you set the start policy of the thread pool attributes to RW_THR_START_INTERRUPTED, that thread pool would hang because all of the threads in the pool would be waiting for RWRunnable::releaseInterrupt() calls. See “Thread Attributes” for more information.
The work queue is treated as if it has unlimited capacity.
Starting a Thread Pool
The make() function begins the process of adding and starting the threads in the thread pool. As each thread is added and started, it immediately begins to query the work queue in order to execute any work that is enqueued there.
Enqueuing Work on a Thread Pool
You use the enqueue() member to enqueue work that is in a function enclosed in an RWTFunctor<void()> object. You may enqueue a variety of different work functions in the same thread pool but each new work function must be encapsulated in an RWTFunctor<void()> object. Work functors can be enqueued only between the construction of the thread pool and a call to stop(). Any attempt to enqueue work after stop() produces an exception.
It is important to note that all work functors must be valid; that is, RWTFunctor<void()>::isValid() must return true.
All exceptions that might be thrown within the functor must be handled within the functor.
Invalid functors, and exceptions thrown by functors but not caught within the same functor, will be ignored in the release version of the compiled source code. During initial development, therefore, you should compile source code in debug mode, which will throw assertions when invalid functors are found or uncaught exceptions are thrown.
Stopping a Thread Pool
The stop() member is used to shut down the thread pool.
Calling stop() to shut down a thread pool causes the thread pool to close the work queue after the thread pool completes all work presently enqueued. Then thread pool joins and removes each thread in the thread pool. Each thread pool will stop only after completing execution of any enqueued work. Should a work functor within the pool be deadlocked or running in an infinite loop, then the thread pool will never complete its shutdown.
Considerations
This section discusses some considerations to keep in mind when dealing with thread pools.
Pool Thread Attributes
Every thread in a thread pool can be initialized using a thread attributes instance when you call make(). All threads created following thread pool startup will have the same attributes, because the pool attributes are copied when the thread pool is started. You cannot change the thread attributes once you have specified them in the make() function that created the thread pool.
Pool Expansion and Contraction
A thread pool can have a fixed number of threads or its size may grow and shrink dynamically according to load. The dynamic nature of the pool is controlled by parameters the creator member function, make(). You can control the minimum and maximum size of the pool as well as how long an idle thread will wait without work before exiting.