BDE 4.14.0 Production release
|
Provide a pool of queues, each processed serially by a thread pool.
This component defines a dynamic, configurable pool of queues, each of which is processed by a thread in a thread pool, such that elements on a given queue are processed serially, regardless of which thread is processing the queue at a given time.
A bdlmt::MultiQueueThreadPool
allows clients to create and delete queues, and to enqueue "jobs" (represented as client-specified functors) to specific queues. Queue processing is implemented on top of a bdlmt::ThreadPool
by enqueuing a per-queue functor to the thread pool. Each functor dequeues the next item from its associated queue, processes it, and re-enqueues itself to the thread pool. Since there is at most one representative functor per queue, each queue is guaranteed to be processed serially by the thread pool.
In addition to the ability to create, delete, pause, and resume queues, clients are able to tune the underlying thread pool in accordance with the bdlmt::ThreadPool
documentation.
bdlmt::MultiQueueThreadPool
allows clients to disable and re-enable queues. A disabled queue will allow no further jobs to be enqueued, but will continue to process the jobs that were enqueued prior to the call to disableQueue
. Note that calling disableQueue
will block the calling thread until the currently executing job (if any) on that queue completes.
bdlmt::MultiQueueThreadPool
also allows clients to pause and resume queues. Pausing a queue suspends the processing of jobs from a queue – i.e., after pause
returns no further jobs will be processed on that queue until the queue is resumed. Note that calling pauseQueue
will block the calling thread until the currently executing job (if any) on that queue completes.
The bdlmt::MultiQueueThreadPool
class is fully thread-safe (i.e., all public methods of a particular instance may safely execute concurrently). This class is also thread-enabled (i.e., the class does not function correctly in a non-multi-threading environment). See bsldoc_glossary for complete definitions of fully thread-safe and thread-enabled.
bdlmt::MultiQueueThreadPool
allows clients to configure the maximum size of a group of jobs that a queue will execute "atomically". "Atomically", in this context, means that no state changes to the queue will be observed by that queue during the processing of the collection of jobs (e.g., a call to pause
will only pause the queue after the currently executing group of jobs completes execution). By default a queue's batch size is 1. Configuring a larger batch size may improve throughput by reducing the synchronization overhead needed to execute a job. However, for many use-cases the overall throughput is limited by the time it takes to process a job (rather than synchronization overhead), so users are strongly encouraged to use benchmarks to guide their decision when setting this option.
To facilitate debugging, users can provide a thread name as the threadName
attribute of the bslmt::ThreadAttributes
argument passed to the constructor, that will be used for all the sub-threads. The thread name should not be used programmatically, but will appear in debugging tools on platforms that support naming threads to help users identify the source and purpose of a thread. If no ThreadAttributes
object is passed, or if the threadName
attribute is not set, the default value "bdl.MultiQuePl" will be used. Note that this only applies to a bdlmt::ThreadPool
automatically created by a bdlmt::MultiQueueThreadPool
. If a thread pool already exists and is passed to the multi queue thread pool at construction, the subthreads will be named however was specified when that thread pool was created.
This section illustrates intended use of this component.
This example illustrates the use of a bdlmt::MultiQueueThreadPool
in a word search application called fastSearch
. fastSearch
searches a list of files for a list of words, and returns the set of files which contain all of the specified words. bdlmt::MultiQueueThreadPool
is used to provide concurrent processing of files, and to simplify the collection of results by serializing access to result sets which are maintained for each word.
First, we present a class used to manage a word, and the set of files which contain that word:
And the implementation:
Next, we define a helper function to perform a search of a word in a particular file. The function is parameterized by a search profile and a file name. If the specified file name matches the profile, it is inserted into the profile's file list.
Lastly, we present the front end to the search application: fastSearch
. fastSearch
is parameterized by a list of words to search for, a list of files to search in, and a set which is populated with the search results. fastSearch
instantiates a bdlmt::MultiQueueThreadPool
, and creates a queue for each word. It then associates each queue with a search profile based on a word in the word list. Then, it enqueues a job to each queue for each file in the file list that tries to match the file to each search profile. Lastly, fastSearch
collects the results, which is the set intersection of each file set maintained by the individual search profiles.