BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlmt.h
Go to the documentation of this file.
1/// @file bdlmt.h
2///
3///
4/// @defgroup bdlmt Package bdlmt
5/// @brief Basic Development Library Multi Thread (bdlmt)
6/// @addtogroup bdl
7/// @{
8/// @addtogroup bdlmt
9/// @{
10/// * <a href="#bdlmt-purpose"> Purpose</a>
11/// * <a href="#bdlmt-mnemonic"> Mnemonic </a>
12/// * <a href="#bdlmt-description"> Description </a>
13/// * <a href="#bdlmt-hierarchical-synopsis"> Hierarchical Synopsis </a>
14/// * <a href="#bdlmt-component-synopsis"> Component Synopsis </a>
15/// * <a href="#bdlmt-generic-overview-of-thread-pools"> Generic Overview of Thread Pools </a>
16/// * <a href="#bdlmt-synchronous-signals-on-unix"> Synchronous Signals on Unix </a>
17///
18/// # Purpose {#bdlmt-purpose}
19/// Provides thread pools and event schedulers.
20///
21/// # Mnemonic {#bdlmt-mnemonic}
22/// Basic Development Library Multi Thread (bdlmt)
23///
24/// @see bdlcc
25///
26/// # Description {#bdlmt-description}
27/// The 'bdlmt' ("Basic Development Library Multi Thread") package
28/// provides components for creating and managing thread pools, and components for
29/// scheduling (time-based) events.
30///
31/// A "thread pool" is a collection of processor threads that are managed
32/// together and used interchangeably to support user requests. The
33/// @ref bdlmt_threadpool component allows clients to configure the pool so that it
34/// grows and shrinks according to user demand, manage thread availability, and
35/// schedule client "jobs" to be run independently as threads in the pool become
36/// available. It does this by placing client requests on an internal job
37/// queue, and controlling multiple threads as they remove jobs from the queue
38/// and execute them.
39///
40/// A "multi-queue thread pool" defines a dynamic, configurable pool of queues,
41/// each of which is processed by a thread in a thread pool, such that elements
42/// on a given queue are processed serially, regardless of which thread is
43/// processing the queue at a given time. In addition to the ability to create
44/// and delete queues, clients are able to tune the underlying thread pool.
45///
46/// A "timer-event scheduler" defines a thread-safe event scheduler. It
47/// provides methods to schedule and cancel recurring and non-recurring events
48/// (also referred to as clock). The callbacks are processed by a separate
49/// thread (called dispatcher thread).
50///
51/// ## Hierarchical Synopsis {#bdlmt-hierarchical-synopsis}
52///
53/// The 'bdlmt' package currently has 9 components having 2 levels of physical
54/// dependency. The list below shows the hierarchical ordering of the components.
55/// The order of components within each level is not architecturally significant,
56/// just alphabetical.
57/// @code
58/// 2. bdlmt_multiqueuethreadpool
59/// bdlmt_threadmultiplexor
60///
61/// 1. bdlmt_eventscheduler
62/// bdlmt_fixedthreadpool
63/// bdlmt_multiprioritythreadpool
64/// bdlmt_signaler
65/// bdlmt_threadpool
66/// bdlmt_throttle
67/// bdlmt_timereventscheduler
68/// @endcode
69///
70/// ## Component Synopsis {#bdlmt-component-synopsis}
71///
72/// @ref bdlmt_eventscheduler :
73/// Provide a thread-safe recurring and one-time event scheduler.
74///
75/// @ref bdlmt_fixedthreadpool :
76/// Provide portable implementation for a fixed-size pool of threads.
77///
78/// @ref bdlmt_multiprioritythreadpool :
79/// Provide a mechanism to parallelize a prioritized sequence of jobs.
80///
81/// @ref bdlmt_multiqueuethreadpool :
82/// Provide a pool of queues, each processed serially by a thread pool.
83///
84/// @ref bdlmt_signaler :
85/// Provide an implementation of a managed signals and slots system.
86///
87/// @ref bdlmt_threadmultiplexor :
88/// Provide a mechanism for partitioning a collection of threads.
89///
90/// @ref bdlmt_threadpool :
91/// Provide portable implementation for a dynamic pool of threads.
92///
93/// @ref bdlmt_throttle :
94/// Provide mechanism for limiting the rate at which actions may occur.
95///
96/// @ref bdlmt_timereventscheduler :
97/// Provide a thread-safe recurring and non-recurring event scheduler.
98///
99/// ## Generic Overview of Thread Pools {#bdlmt-generic-overview-of-thread-pools}
100///
101/// At the current time, this generic overview applies only to the
102/// 'bdlmt_MultipriorityThreadPool'. The plan is for other threadpools to move
103/// to this model at a later date.
104///
105/// As Figure 1 illustrates, a threadpool allows its clients to enqueue units of
106/// work to be processed concurrently in multiple threads. Each work item, or
107/// "job", consists of a function along with the address of its associated input
108/// data. When executed, this address is supplied to the function as its only
109/// argument; note that this function must have external linkage and return
110/// 'void':
111/// @code
112/// extern "C" void job(void *); // Idiomatic C-style function signature
113/// @endcode
114/// Alternatively both the function and its data can be encapsulated and
115/// supplied in the form of an (invokable) function object, or "functor", taking
116/// no arguments and returning 'void'.
117/// @code
118/// +-------------------------------------------------------------------------+
119/// | ThreadPool *Control* Methods |
120/// | |
121/// | Front Operations Middle Operations Back Operations |
122/// | ---------------- ----------------- --------------- |
123/// | int startThreads() void removeJobs() void enableQueue() |
124/// | void stopThreads() void drainJobs() void disableQueue() |
125/// | int resumeProcessing() int enqueueJob(func,arg) |
126/// | int suspendProcessing() int enqueueJob(job) |
127/// | |
128/// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -+
129/// | +--<--+--<--+--<--+--<--+--<--+----------------+ |
130/// | | | | | | | | |
131/// | Front <==| Job | Job | Job | Job | Job | |==< Back |
132/// | | | | | | | | |
133/// | +--<--+--<--+--<--+--<--+--<--+----------------+ |
134/// | |
135/// | ,----------------. ,-----------------. |
136/// | ( N Worker Threads ) ( Thread Attributes ) |
137/// | `----------------' `-----------------' |
138/// +-------------------------------------------------------------------------+
139/// Figure 1: Illustration of Generalized Thread Pool
140/// @endcode
141/// In addition to enqueuing jobs, a thread pool must supply primitive control
142/// functionality such as creating and destroying worker threads, enabling and
143/// disabling the enqueuing of new jobs, causing the queue to block until there
144/// are no pending jobs, and removing (i.e., canceling) all pending (i.e., not
145/// yet running) jobs. Different kinds of threadpools will provide different
146/// functionality and/or performance characteristics, corresponding those of the
147/// underlying thread-enabled ('bdlcc') queue -- e.g., (limited-capacity)
148/// 'FixedQueue', (heap-based) 'PriorityQueue', and (array-based)
149/// 'MultipriorityQueue'. Nonetheless, each of the threadpool objects in 'bdlmt'
150/// should provide a suite of input and control operations that are consistent
151/// in both name and behavior across the 'bdlmt' package.
152///
153/// Due to the intricate nature of threadpools, it is easy to convolve behaviors
154/// in subtly different ways for functions having the same name. Consider, for
155/// example, the method 'void drainJobs()', the basic functionality of which is
156/// to 'block' the caller until all of the pending jobs complete (i.e., the
157/// queue is empty and all worker threads are idle). Should 'drainJobs()' also
158/// leave the queue in the disabled state? Even if that is a common usage
159/// pattern, it is often useful to start with simple, orthogonal behaviors, and
160/// if needed, define more complex behaviors in terms of them.
161///
162/// In the case of a thread pool, it is instructive to break the functionality
163/// into three categories of operations relative to the underlying queue: Front,
164/// Middle, and Back. At the back of the queue (refer to Figure 1), we need to
165/// enable/disable clients from adding work items. Enabling or disabling the
166/// queue does not affect the items already in the queue [Middle], nor any
167/// worker threads processing these items [Front].
168///
169/// In the middle of the queue, we have two operations that result in purging
170/// all pending items in the queue: 'drainJobs()' and 'removeJobs()' If we
171/// invoke 'removeJobs()', then all currently pending (i.e., not started) work
172/// items will be removed (i.e., canceled). During this process, clients
173/// attempting to add work items [Back] will block, but their eventual success
174/// or failure, (which is based solely on whether the queue is enabled or
175/// disabled) is not affected. Note that jobs that are already in progress
176/// [Front] are also unaffected. Similarly, invoking our orthogonal
177/// 'drainJobs()' method will block enqueuing clients until all pending jobs
178/// have completed, but will not affect the enabledness of the thread pool
179/// [Back], nor the processing of work items [Front].
180///
181/// Finally we come to the front of the queue, which addresses the processing of
182/// jobs. A (typically fixed) number of worker threads is specified at
183/// construction. The thread pool "wakes up" in an enabled state, but without
184/// having created the worker threads. Invoking the 'startThreads()' method
185/// attempts to create these threads (unless they are already created). The
186/// 'startThreads()' method returns 0 if all of these threads are started, and a
187/// non-zero value otherwise (in which case none of the worker threads are
188/// started). Redundant calls to 'startThreads()' do nothing and return zero.
189/// Invoking 'stopThreads()' destroys each worker thread (after it completes any
190/// current job). Note that the current contents of the queue [Middle], and the
191/// ability to enqueue new jobs [Back] are not affected.
192///
193/// Whether or not started threads should be pulling jobs from the queue and
194/// processing them is not necessarily the same as having the user-specified
195/// number of worker threads created. In addition to being *enabled* and
196/// *started* let's consider one more possible state, *suspended*. If a thread
197/// pool is in the *suspended* state, then even when it is in the *started*
198/// state, it will not attempt to pop jobs from the queue and execute them.
199///
200/// A created threadpool will be created enabled, not suspended, and not
201/// started. All three of these qualities are orthogonal and any one of them
202/// can be changed at any time.
203///
204/// The vast majority of users will be uninterested in both the 'suspend' and
205/// 'disable' features, so it is imperative that newly created threadpools be
206/// both non-suspended and enabled so users can remain blissfully ignorant of
207/// them. It is also important the first usage examples, if not all of them,
208/// omit use of these features to minimize learning time for the typical user.
209///
210/// To conclude this generic overview, we note that there is one common usage
211/// that, although not minimal, arguably deserves to be a method of every thread
212/// pool class: 'void shutdown()'. This method is best described as a
213/// composition of the simple, orthogonal functions described above. In order
214/// to shut down a thread pool, we need to first disable the enqueuing of any
215/// additional jobs, then remove all of the pending work items, and finally stop
216/// all of the active threads:
217/// @code
218/// void shutdown()
219/// {
220/// disableQueue();
221/// removeJobs();
222/// stopThreads();
223/// }
224/// @endcode
225/// By making sure that our initial operations are simple and orthogonal, we can
226/// ensure that the precise meaning of more complex operations is kept clear.
227///
228/// ## Synchronous Signals on Unix {#bdlmt-synchronous-signals-on-unix}
229///
230/// A thread pool ensures that, on Unix platforms, all the threads in the pool
231/// block all asynchronous signals. Specifically all the signals, except the
232/// following synchronous signals are blocked.
233/// @code
234/// SIGBUS
235/// SIGFPE
236/// SIGILL
237/// SIGSEGV
238/// SIGSYS
239/// SIGABRT
240/// SIGTRAP
241/// SIGIOT
242/// @endcode
243///
244/// @}
245/** @} */