BDE 4.39.x 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 `void operator()()`.
196 ///
197 /// \note Note that threads are always created joinable,
198 /// regardless of the mode specified in `attributes`.
199 template <class INVOKABLE>
200 int addThread(const INVOKABLE& functor);
201 template <class INVOKABLE>
202 int addThread(const INVOKABLE& functor,
203 const ThreadAttributes& attributes);
204
205 /// Begin executing the specified invokable `functor` in the specified
206 /// new `numThreads`, using the optionally specified thread
207 /// `attributes`. Return `numThreads` on success, or the number of
208 /// threads successfully started otherwise. `INVOKABLE` shall be a
209 /// copy-constructible type having the equivalent of `void operator()()`.
210 ///
211 /// \note Note that threads are always created joinable,
212 /// regardless of the mode specified in `attributes`.
213 template <class INVOKABLE>
214 int addThreads(const INVOKABLE& functor, int numThreads);
215 template <class INVOKABLE>
216 int addThreads(const INVOKABLE& functor,
217 int numThreads,
218 const ThreadAttributes& attributes);
219
220 /// Block the calling thread until all threads started in this group
221 /// have finished executing.
222 void joinAll();
223
224 // ACCESSORS
225
226 /// Return a snapshot of the number of threads started in this group
227 /// that have not been joined.
228 int numThreads() const;
229};
230
231// ============================================================================
232// INLINE DEFINITIONS
233// ============================================================================
234
235 // -----------------
236 // class ThreadGroup
237 // -----------------
238
239// MANIPULATORS
240template<class INVOKABLE>
241inline
242int ThreadGroup::addThread(const INVOKABLE& functor)
243{
244 return addThread(functor, ThreadAttributes());
245}
246
247template<class INVOKABLE>
248inline
249int ThreadGroup::addThreads(const INVOKABLE& functor, int numThreads)
250{
251 return addThreads(functor, numThreads, ThreadAttributes());
252}
253
254template<class INVOKABLE>
255int ThreadGroup::addThread(const INVOKABLE& functor,
256 const ThreadAttributes& attributes)
257{
258 ThreadUtil::Handle handle;
259 int rc = 1;
261 ThreadAttributes newAttributes(attributes);
264 &handle,
265 newAttributes,
266 functor,
267 d_threads.get_allocator().mechanism());
268 }
269 else {
271 &handle,
272 attributes,
273 functor,
274 d_threads.get_allocator().mechanism());
275 }
276
277 if (0 == rc) {
278 addThread(handle);
279 }
280 return rc;
281}
282
283template <class INVOKABLE>
284int ThreadGroup::addThreads(const INVOKABLE& functor,
285 int numThreads,
286 const ThreadAttributes& attributes)
287{
289
290 int numAdded;
291 for (numAdded = 0; numAdded < numThreads; ++numAdded) {
292 if (0 != addThread(functor, attributes)) {
293 break;
294 }
295 }
296 return numAdded;
297}
298
299// ACCESSORS
300inline
302{
303 return d_numThreads.loadRelaxed();
304}
305
306} // close package namespace
307
308// ============================================================================
309// TYPE TRAITS
310// ============================================================================
311
312namespace bslma {
313
314template <>
315struct UsesBslmaAllocator<bslmt::ThreadGroup> : bsl::true_type {};
316
317} // close namespace bslma
318
319
320#endif
321
322// ----------------------------------------------------------------------------
323// Copyright 2015 Bloomberg Finance L.P.
324//
325// Licensed under the Apache License, Version 2.0 (the "License");
326// you may not use this file except in compliance with the License.
327// You may obtain a copy of the License at
328//
329// http://www.apache.org/licenses/LICENSE-2.0
330//
331// Unless required by applicable law or agreed to in writing, software
332// distributed under the License is distributed on an "AS IS" BASIS,
333// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
334// See the License for the specific language governing permissions and
335// limitations under the License.
336// ----------------------------- END-OF-FILE ----------------------------------
337
338/** @} */
339/** @} */
340/** @} */
Definition bslstl_vector.h:1120
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_vector.h:4621
Definition bslma_allocator.h:545
Definition bslmt_mutex.h:317
Definition bslmt_threadattributes.h:361
@ e_CREATE_JOINABLE
Definition bslmt_threadattributes.h:370
DetachedState detachedState() const
Definition bslmt_threadattributes.h:736
ThreadAttributes & setDetachedState(DetachedState value)
Definition bslmt_threadattributes.h:662
Definition bslmt_threadgroup.h:156
int numThreads() const
Definition bslmt_threadgroup.h:301
ThreadGroup(bslma::Allocator *basicAllocator=0)
int addThreads(const INVOKABLE &functor, int numThreads)
Definition bslmt_threadgroup.h:249
Definition bsls_atomic.h:744
int loadRelaxed() const
Definition bsls_atomic.h:1759
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_encoder_testtypes.h:76
Definition bslmt_barrier.h:344
Definition bslma_usesbslmaallocator.h:344
Imp::Handle Handle
Definition bslmt_threadutil.h:389
static int createWithAllocator(Handle *handle, ThreadFunction function, void *userData, bslma::Allocator *allocator)