BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_threadgroup.h
Go to the documentation of this file.
1/// @file bslmt_threadgroup.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_threadgroup.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_THREADGROUP
9#define INCLUDED_BSLMT_THREADGROUP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmt_threadgroup bslmt_threadgroup
15/// @brief Provide a container for managing a group of threads.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_threadgroup
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_threadgroup-purpose"> Purpose</a>
25/// * <a href="#bslmt_threadgroup-classes"> Classes </a>
26/// * <a href="#bslmt_threadgroup-description"> Description </a>
27/// * <a href="#bslmt_threadgroup-thread-safety"> Thread Safety </a>
28/// * <a href="#bslmt_threadgroup-usage"> Usage </a>
29/// * <a href="#bslmt_threadgroup-example-1-basic-usage"> Example 1: Basic Usage </a>
30///
31/// # Purpose {#bslmt_threadgroup-purpose}
32/// Provide a container for managing a group of threads.
33///
34/// # Classes {#bslmt_threadgroup-classes}
35///
36/// - bslmt::ThreadGroup: A container that manages a group of threads.
37///
38/// @see bslmt_threadutil, bslmt_threadattributes
39///
40/// # Description {#bslmt_threadgroup-description}
41/// This component provides a simple mechanism for managing a group
42/// of threads. The group is represented by an instance of the
43/// `bslmt::ThreadGroup` class. To use this component, the client code calls
44/// `addThread`, providing a function to be executed. The specified function is
45/// executed in a new thread managed by the thread group (note that `addThread`
46/// is thread-safe). The `joinAll` call blocks until all threads in the group
47/// have finished executing.
48///
49/// ## Thread Safety {#bslmt_threadgroup-thread-safety}
50///
51///
52/// This component is thread-safe and thread-enabled, meaning that multiple
53/// threads may safely use their own instances or a shared instance of a
54/// `bslmt::ThreadGroup` object.
55///
56/// ## Usage {#bslmt_threadgroup-usage}
57///
58///
59/// This section illustrates intended use of this component.
60///
61/// ### Example 1: Basic Usage {#bslmt_threadgroup-example-1-basic-usage}
62///
63///
64/// The following usage example illustrates how `bslmt::ThreadGroup` might be
65/// used in a typical test driver to simplify the execution of a common function
66/// in multiple threads. Suppose that we are interested in creating a
67/// stress-test for the `bslmt::Mutex` class. The test is controlled by two
68/// parameters: the number of executions (defined by subsequent calls to `lock`
69/// and `unlock`, and the amount of contention, defined by the number of threads
70/// accessing the mutex. The test can be expressed as two functions. The first
71/// is executed in each thread via a functor object:
72/// @code
73/// class MutexTestJob {
74/// int d_numIterations;
75/// int *d_value_p;
76/// bslmt::Mutex *d_mutex_p;
77///
78/// public:
79/// MutexTestJob(int numIterations, int *value, bslmt::Mutex *mutex)
80/// : d_numIterations(numIterations)
81/// , d_value_p(value)
82/// , d_mutex_p(mutex)
83/// {}
84///
85/// void operator()() {
86/// for (int i = 0; i < d_numIterations; ++i) {
87/// bslmt::LockGuard<bslmt::Mutex> guard(d_mutex_p);
88/// ++*d_value_p;
89/// }
90/// }
91/// };
92/// @endcode
93/// The second executes the main body of the test:
94/// @code
95/// bslma::TestAllocator ta;
96/// {
97/// const int NUM_ITERATIONS = 10000;
98/// const int NUM_THREADS = 8;
99///
100/// bslmt::Mutex mutex; // object under test
101/// int value = 0;
102///
103/// MutexTestJob testJob(NUM_ITERATIONS, &value, &mutex);
104///
105/// bslmt::ThreadGroup threadGroup(&ta);
106/// for (int i = 0; i < NUM_THREADS; ++i) {
107/// assert(0 == threadGroup.addThread(testJob));
108/// }
109/// threadGroup.joinAll();
110/// assert(NUM_ITERATIONS * NUM_THREADS == value);
111/// }
112/// assert(0 < ta.numAllocations());
113/// assert(0 == ta.numBytesInUse());
114/// @endcode
115/// @}
116/** @} */
117/** @} */
118
119/** @addtogroup bsl
120 * @{
121 */
122/** @addtogroup bslmt
123 * @{
124 */
125/** @addtogroup bslmt_threadgroup
126 * @{
127 */
128
129#include <bslscm_version.h>
130
131#include <bslmt_mutex.h>
133#include <bslmt_threadutil.h>
134
135#include <bslma_allocator.h>
137
138#include <bsls_assert.h>
139#include <bsls_atomic.h>
140
141#include <bsl_vector.h>
142
143
144namespace bslmt {
145
146 // =================
147 // class ThreadGroup
148 // =================
149
150/// This class provides a simple mechanism for managing a group of joinable
151/// threads. The destructor ensures that any running threads are detached
152/// so that resources are not leaked. This class is thread-enabled,
153/// thread-safe, and exception-neutral.
154///
155/// See @ref bslmt_threadgroup
157
158 // PRIVATE TYPES
160
161 // INSTANCE DATA
162 bsls::AtomicInt d_numThreads;
163 ThreadContainer d_threads;
164 Mutex d_threadsMutex;
165
166 // PRIVATE MANIPULATORS
167
168 /// Add the specified `handle` to the `d_threads` container. If an
169 /// exception is thrown, `handle` will be released.
170 void addThread(const ThreadUtil::Handle& handle);
171
172 private:
173 // not implemented
174 ThreadGroup(const ThreadGroup&);
175 ThreadGroup& operator=(const ThreadGroup&);
176
177 public:
178 // CREATORS
179
180 /// Create an empty thread group. Optionally specify `basicAllocator`
181 /// will be used to supply memory. If `basicAllocator` is 0, the
182 /// currently installed default allocator will be used.
183 explicit
184 ThreadGroup(bslma::Allocator *basicAllocator = 0);
185
186 /// Destroy this object. Any threads not joined will be allowed to run
187 /// independently, and will no longer be joinable.
189
190 // MANIPULATORS
191
192 /// Begin executing the specified invokable `functor` in a new thread,
193 /// using the optionally specified thread `attributes`. Return 0 on
194 /// success, and a non-zero value otherwise. `INVOKABLE` shall be a
195 /// copy-constructible type having the equivalent of
196 /// `void operator()()`. Note that threads are always created joinable,
197 /// regardless of the mode specified in `attributes`.
198 template <class INVOKABLE>
199 int addThread(const INVOKABLE& functor);
200 template <class INVOKABLE>
201 int addThread(const INVOKABLE& functor,
202 const ThreadAttributes& attributes);
203
204 /// Begin executing the specified invokable `functor` in the specified
205 /// new `numThreads`, using the optionally specified thread
206 /// `attributes`. Return `numThreads` on success, or the number of
207 /// threads successfully started otherwise. `INVOKABLE` shall be a
208 /// copy-constructible type having the equivalent of
209 /// `void operator()()`. Note that threads are always created joinable,
210 /// regardless of the mode specified in `attributes`.
211 template <class INVOKABLE>
212 int addThreads(const INVOKABLE& functor, int numThreads);
213 template <class INVOKABLE>
214 int addThreads(const INVOKABLE& functor,
215 int numThreads,
216 const ThreadAttributes& attributes);
217
218 /// Block the calling thread until all threads started in this group
219 /// have finished executing.
220 void joinAll();
221
222 // ACCESSORS
223
224 /// Return a snapshot of the number of threads started in this group
225 /// that have not been joined.
226 int numThreads() const;
227};
228
229// ============================================================================
230// INLINE DEFINITIONS
231// ============================================================================
232
233 // -----------------
234 // class ThreadGroup
235 // -----------------
236
237// MANIPULATORS
238template<class INVOKABLE>
239inline
240int ThreadGroup::addThread(const INVOKABLE& functor)
241{
242 return addThread(functor, ThreadAttributes());
243}
244
245template<class INVOKABLE>
246inline
247int ThreadGroup::addThreads(const INVOKABLE& functor, int numThreads)
248{
249 return addThreads(functor, numThreads, ThreadAttributes());
250}
251
252template<class INVOKABLE>
253int ThreadGroup::addThread(const INVOKABLE& functor,
254 const ThreadAttributes& attributes)
255{
256 ThreadUtil::Handle handle;
257 int rc = 1;
259 ThreadAttributes newAttributes(attributes);
262 &handle,
263 newAttributes,
264 functor,
265 d_threads.get_allocator().mechanism());
266 }
267 else {
269 &handle,
270 attributes,
271 functor,
272 d_threads.get_allocator().mechanism());
273 }
274
275 if (0 == rc) {
276 addThread(handle);
277 }
278 return rc;
279}
280
281template<class INVOKABLE>
282int ThreadGroup::addThreads(const INVOKABLE& functor,
283 int numThreads,
284 const ThreadAttributes& attributes)
285{
287
288 int numAdded;
289 for (numAdded = 0; numAdded < numThreads; ++numAdded) {
290 if (0 != addThread(functor, attributes)) {
291 break;
292 }
293 }
294 return numAdded;
295}
296
297// ACCESSORS
298inline
300{
301 return d_numThreads.loadRelaxed();
302}
303
304} // close package namespace
305
306// ============================================================================
307// TYPE TRAITS
308// ============================================================================
309
310namespace bslma {
311
312template <>
313struct UsesBslmaAllocator<bslmt::ThreadGroup> : bsl::true_type {};
314
315} // close namespace bslma
316
317
318#endif
319
320// ----------------------------------------------------------------------------
321// Copyright 2015 Bloomberg Finance L.P.
322//
323// Licensed under the Apache License, Version 2.0 (the "License");
324// you may not use this file except in compliance with the License.
325// You may obtain a copy of the License at
326//
327// http://www.apache.org/licenses/LICENSE-2.0
328//
329// Unless required by applicable law or agreed to in writing, software
330// distributed under the License is distributed on an "AS IS" BASIS,
331// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
332// See the License for the specific language governing permissions and
333// limitations under the License.
334// ----------------------------- END-OF-FILE ----------------------------------
335
336/** @} */
337/** @} */
338/** @} */
BloombergLP::bslma::Allocator * mechanism() const
Definition bslma_bslallocator.h:1126
Definition bslstl_vector.h:1025
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:4019
Definition bslma_allocator.h:457
Definition bslmt_mutex.h:315
Definition bslmt_threadattributes.h:356
@ e_CREATE_JOINABLE
Definition bslmt_threadattributes.h:365
DetachedState detachedState() const
Definition bslmt_threadattributes.h:725
ThreadAttributes & setDetachedState(DetachedState value)
Definition bslmt_threadattributes.h:651
Definition bslmt_threadgroup.h:156
int numThreads() const
Definition bslmt_threadgroup.h:299
ThreadGroup(bslma::Allocator *basicAllocator=0)
int addThreads(const INVOKABLE &functor, int numThreads)
Definition bslmt_threadgroup.h:247
Definition bsls_atomic.h:743
int loadRelaxed() const
Definition bsls_atomic.h:1738
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68
Definition bslmt_barrier.h:344
Definition bslma_usesbslmaallocator.h:343
Imp::Handle Handle
Definition bslmt_threadutil.h:385
static int createWithAllocator(Handle *handle, ThreadFunction function, void *userData, bslma::Allocator *allocator)