BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmt_entrypointfunctoradapter.h
Go to the documentation of this file.
1/// @file bslmt_entrypointfunctoradapter.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmt_entrypointfunctoradapter.h -*-C++-*-
8#ifndef INCLUDED_BSLMT_ENTRYPOINTFUNCTORADAPTER
9#define INCLUDED_BSLMT_ENTRYPOINTFUNCTORADAPTER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$: $")
13
14/// @defgroup bslmt_entrypointfunctoradapter bslmt_entrypointfunctoradapter
15/// @brief Provide types and utilities to simplify thread creation.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmt
19/// @{
20/// @addtogroup bslmt_entrypointfunctoradapter
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmt_entrypointfunctoradapter-purpose"> Purpose</a>
25/// * <a href="#bslmt_entrypointfunctoradapter-classes"> Classes </a>
26/// * <a href="#bslmt_entrypointfunctoradapter-description"> Description </a>
27/// * <a href="#bslmt_entrypointfunctoradapter-usage"> Usage </a>
28/// * <a href="#bslmt_entrypointfunctoradapter-example-1-wrapping-a-c-invokable-type"> Example 1: Wrapping a C++ Invokable Type </a>
29///
30/// # Purpose {#bslmt_entrypointfunctoradapter-purpose}
31/// Provide types and utilities to simplify thread creation.
32///
33/// # Classes {#bslmt_entrypointfunctoradapter-classes}
34///
35/// - EntryPointFunctorAdapter: Encapsulate invokable object with allocator.
36/// - EntryPointFunctorAdapterUtil: Dynamic allocation of adapter objects.
37///
38/// # Description {#bslmt_entrypointfunctoradapter-description}
39/// This component defines a type, `EntryPointFunctorAdapter`, that
40/// contains a single instance of a parameterized invokable type along with an
41/// allocator to manage it. The parameterized type must provide a copy
42/// constructor and `void operator()()`.
43///
44/// This component also provides a C-linkage function
45/// `bslmt_EntryPointFunctorAdapter_invoker` that operates on a pointer to
46/// `EntryPointFunctorAdapter`, invoking the invokable object contained within
47/// it and then deallocating the adapter object along with the contained
48/// invokable object. Together, `EntryPointFunctorAdapter` and
49/// `bslmt_EntryPointFunctorAdapter_invoker` simplify the process of invoking a
50/// generic functor as a C-style callback, such as a thread entry point.
51///
52/// Finally, this component provides `EntryPointFunctorAdapterUtil`, a namespace
53/// for a utility function that dynamically allocates instances of
54/// `EntryPointFunctorAdapter`.
55///
56/// ## Usage {#bslmt_entrypointfunctoradapter-usage}
57///
58///
59/// This section illustrates the intended use of this component.
60///
61/// ### Example 1: Wrapping a C++ Invokable Type {#bslmt_entrypointfunctoradapter-example-1-wrapping-a-c-invokable-type}
62///
63///
64/// Suppose we have an existing interface for invoking a C-linkage function and
65/// passing a void* argument to it. This situation may arise when starting
66/// threads or in general when registering a C-style callback. A simplistic
67/// example of such a function is:
68/// @code
69/// extern "C" {
70/// typedef void *(*CallbackFunction)(void*);
71/// }
72///
73/// void *executeWithArgument(CallbackFunction funcPtr, void *argument)
74/// {
75/// return funcPtr(argument);
76/// }
77/// @endcode
78/// In this example, we want to use this interface to invoke a C++-style
79/// functor. Our approach will be to use
80/// `bslmt_EntryPointFunctorAdapter_invoker` as the C-linkage callback function,
81/// and a dynamically allocated value of `EntryPointFunctorAdapter` as the
82/// `void*` argument.
83///
84/// First, we define a C++ functor type. This type implements the job of
85/// counting the number of words in a string held by value.
86/// @code
87/// class WordCountJob {
88/// // DATA
89/// bsl::string d_message;
90/// int *d_result_p; // held, not owned
91///
92/// public:
93/// // TRAITS
94/// BSLMF_NESTED_TRAIT_DECLARATION(WordCountJob,
95/// bslma::UsesBslmaAllocator);
96///
97/// // CREATORS
98///
99/// /// Create a new functor that, upon execution, counts the number of
100/// /// words (contiguous sequences of non-space characters) in the
101/// /// specified `message` and stores the count in the specified
102/// /// `result` address. Optionally specify a `basicAllocator` used to
103/// /// supply memory. If `basicAllocator` is 0, the currently
104/// /// installed default allocator is used.
105/// WordCountJob(const bslstl::StringRef& message,
106/// int *result,
107/// bslma::Allocator *basicAllocator = 0);
108///
109/// /// Create a new functor that performs the same calculation as the
110/// /// specified `other` functor. Optionally specify a
111/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
112/// /// 0, the currently installed default allocator is used.
113/// WordCountJob(const WordCountJob& original,
114/// bslma::Allocator *basicAllocator = 0);
115///
116/// // MANIPULATORS
117///
118/// /// Count the number of words in the message and store the count in
119/// /// the address specified on construction.
120/// void operator()();
121/// };
122///
123/// inline
124/// WordCountJob::WordCountJob(const bslstl::StringRef& message,
125/// int *result,
126/// bslma::Allocator *basicAllocator)
127/// : d_message(message, basicAllocator)
128/// , d_result_p(result)
129/// {}
130///
131/// inline
132/// WordCountJob::WordCountJob(const WordCountJob& original,
133/// bslma::Allocator *basicAllocator)
134/// : d_message(original.d_message, basicAllocator)
135/// , d_result_p(original.d_result_p)
136/// {}
137///
138/// void WordCountJob::operator()()
139/// {
140/// bool inWord = false;
141/// *d_result_p = 0;
142/// for (unsigned i = 0; i < d_message.length(); ++i) {
143/// if (isspace(d_message[i])) {
144/// inWord = false;
145/// } else if (!inWord) {
146/// inWord = true;
147/// ++(*d_result_p);
148/// }
149/// }
150/// }
151/// @endcode
152/// Next, we dynamically allocate an `EntryPointFunctorAdapter` wrapping an
153/// instance of this functor:
154/// @code
155/// int result = 0;
156/// WordCountJob job("The quick brown fox jumped over the lazy dog.",
157/// &result);
158///
159/// bslma::ManagedPtr<
160/// bslmt::EntryPointFunctorAdapter<WordCountJob> > threadData;
161/// bslmt::EntryPointFunctorAdapterUtil::allocateAdapter(&threadData,
162/// job,
163/// "");
164/// @endcode
165/// Finally, we use `bslmt_EntryPointFunctorAdapter_invoker` to invoke the job
166/// in the context of a C-linkage function. Note that
167/// `bslmt_EntryPointFunctorAdapter_invoker` will deallocate the adapter object
168/// and the contained invokable job after executing it, so we must release the
169/// adapter from memory management via `ManagedPtr`. (In general, system APIs
170/// that register callbacks may fail; newly allocated adapters are loaded into
171/// `ManagedPtr` to aid in proper error and exception handling, outside the
172/// scope of this example.)
173/// @code
174/// executeWithArgument(bslmt_EntryPointFunctorAdapter_invoker,
175/// threadData.ptr());
176/// threadData.release();
177/// assert(9 == result);
178/// @endcode
179/// @}
180/** @} */
181/** @} */
182
183/** @addtogroup bsl
184 * @{
185 */
186/** @addtogroup bslmt
187 * @{
188 */
189/** @addtogroup bslmt_entrypointfunctoradapter
190 * @{
191 */
192
193#include <bslscm_version.h>
194
195#include <bslmt_platform.h>
198
200
201#include <bslma_allocator.h>
202#include <bslma_default.h>
203#include <bslma_managedptr.h>
205
206#include <bsl_string.h>
207
208
209
210extern "C" {
211
212/// Interpreting `argument` as an `EntryPointFunctorAdapter_Base*`, invoke
213/// `argument->function(argument)`. Do not use outside this component.
215
216}
217
218namespace bslmt {
219
220template <class THREAD_POLICY>
222
224
225/// This component-private type provides a non-templated view of
226/// `EntryPointFunctorAdapter` for accessing the invoker function. Do not
227/// use outside this component.
228///
229/// See @ref bslmt_entrypointfunctoradapter
231
232 public:
233 // PUBLIC TYPES
234
235 /// `InvokerFunction` is an alias for the type of function pointer held
236 /// in an EntryPointFunctorAdapter_Base. Instances of the function are
237 /// intended to interpret their argument as an
238 /// `EntryPointFunctorAdapter<TYPE>*`.
239 typedef void (*InvokerFunction)(void*);
240
241 private:
242 InvokerFunction d_function; // Function to operate on template object
243
244 protected:
245 // PROTECTED CREATORS
246
247 /// Create a new object holding the specified `function`.
249
250 public:
251 // PUBLIC ACCESSORS
252
253 /// Return the function supplied at construction.
255};
256
257/// Hold a copy of an instance of parameterized type, along with the
258/// allocator used to manage the copy. `TYPE` shall have a copy
259/// constructor, and declare the `bslma::UsesBslmaAllocator` trait if it
260/// uses `bslma::Allocator` as an argument to its copy constructor.
261template <typename TYPE>
263
264 // DATA
266 bsl::string d_threadName;
267
268 // FRIENDS
270
271 private:
272 // NOT IMPLEMENTED
275
276 // PRIVATE CREATORS
277
278 /// Create a new managed object holding copies of the specified
279 /// `functor` and `threadName` values and using the specified
280 /// `allocator` to supply memory.
281 EntryPointFunctorAdapter(const TYPE& functor,
282 const bslstl::StringRef& threadName,
283 bslma::Allocator *allocator);
284
285 // PRIVATE CLASS METHODS
286
287 /// Interpreting the specified `adapter` as an
288 /// `EntryPointFunctorAdapter<TYPE>*`, invoke `d_object` and then
289 /// deallocate `adapter` using the allocator used by `*adapter`.
290 static void invokerFunction(void *adapter);
291
292 // PRIVATE MANIPULATORS
293
294 /// Return a reference to the functor.
295 TYPE& functor();
296
297 public:
298 // CREATORS
299
300 /// Destroy this object and the underlying managed object. Note that
301 /// this public destructor is generated by the compiler.
303};
304
306
307 // CLASS METHODS
308
309 /// Allocate a new `EntryPointFunctorAdapter` holding copies of the
310 /// specified `invokable` object and `threadName`, and load the result
311 /// into the specified `adapter`. Optionally specify a `basicAllocator`
312 /// used to supply memory. If `basicAllocator` is 0, the currently
313 /// installed default allocator is used.
314 template<typename TYPE>
315 static void allocateAdapter(
317 const TYPE& invokable,
318 const bslstl::StringRef& threadName,
319 bslma::Allocator *basicAllocator = 0);
320};
321
322// ============================================================================
323// INLINE DEFINITIONS
324// ============================================================================
325
326 // -----------------------------------
327 // class EntryPointFunctorAdapter_Base
328 // -----------------------------------
329
330// PROTECTED CREATORS
331inline
333 InvokerFunction function)
334: d_function(function)
335{}
336
337// PUBLIC ACCESSORS
338inline
341{
342 return d_function;
343}
344
345 // ------------------------------
346 // class EntryPointFunctorAdapter
347 // ------------------------------
348
349// PRIVATE CLASS METHODS
350template <typename TYPE>
351inline
353{
355 static_cast<EntryPointFunctorAdapter<TYPE>*>(adapterRaw);
356
357 bslma::Allocator *a = adapter->d_threadName.get_allocator().mechanism();
359 bslma::Allocator> adapterGuard(adapter, a);
360
361 if (false == adapter->d_threadName.empty()) {
363 adapter->d_threadName);
364 }
365
366 adapter->functor()();
367}
368
369// PRIVATE CREATORS
370template <typename TYPE>
371inline
372EntryPointFunctorAdapter<TYPE>::EntryPointFunctorAdapter(
373 const TYPE& functor,
374 const bslstl::StringRef& threadName,
375 bslma::Allocator *allocator)
376: EntryPointFunctorAdapter_Base(&invokerFunction)
377, d_functor(functor, allocator)
378, d_threadName(threadName, allocator)
379{}
380
381// PRIVATE MANIPULATORS
382template <typename TYPE>
383inline
384TYPE& EntryPointFunctorAdapter<TYPE>::functor()
385{
386 return d_functor.object();
387}
388
389 // ----------------------------------
390 // class EntryPointFunctorAdapterUtil
391 // ----------------------------------
392
393template <typename TYPE>
394inline
397 const TYPE& invokable,
398 const bslstl::StringRef& threadName,
399 bslma::Allocator *basicAllocator)
400{
401 bslma::Allocator *allocator = bslma::Default::allocator(basicAllocator);
402 adapter->load(new (*allocator) EntryPointFunctorAdapter<TYPE>(invokable,
403 threadName,
404 allocator),
405 allocator);
406}
407
408} // close package namespace
409
410
411#endif
412
413// ----------------------------------------------------------------------------
414// Copyright 2015 Bloomberg Finance L.P.
415//
416// Licensed under the Apache License, Version 2.0 (the "License");
417// you may not use this file except in compliance with the License.
418// You may obtain a copy of the License at
419//
420// http://www.apache.org/licenses/LICENSE-2.0
421//
422// Unless required by applicable law or agreed to in writing, software
423// distributed under the License is distributed on an "AS IS" BASIS,
424// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
425// See the License for the specific language governing permissions and
426// limitations under the License.
427// ----------------------------- END-OF-FILE ----------------------------------
428
429/** @} */
430/** @} */
431/** @} */
Definition bslstl_string.h:1281
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this string to supply memory.
Definition bslstl_string.h:6723
bool empty() const BSLS_KEYWORD_NOEXCEPT
Return true if this string has length 0, and false otherwise.
Definition bslstl_string.h:6631
Definition bslalg_constructorproxy.h:368
Definition bslma_allocator.h:457
Definition bslma_managedptr.h:1182
Definition bslma_rawdeleterguard.h:217
Definition bslmt_entrypointfunctoradapter.h:230
InvokerFunction function() const
Return the function supplied at construction.
Definition bslmt_entrypointfunctoradapter.h:340
EntryPointFunctorAdapter_Base(InvokerFunction function)
Create a new object holding the specified function.
Definition bslmt_entrypointfunctoradapter.h:332
void(* InvokerFunction)(void *)
Definition bslmt_entrypointfunctoradapter.h:239
Definition bslmt_entrypointfunctoradapter.h:262
Definition bslstl_stringref.h:372
void * bslmt_EntryPointFunctorAdapter_invoker(void *argument)
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslmt_barrier.h:344
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897
Definition bslmt_entrypointfunctoradapter.h:305
static void allocateAdapter(bslma::ManagedPtr< EntryPointFunctorAdapter< TYPE > > *adapter, const TYPE &invokable, const bslstl::StringRef &threadName, bslma::Allocator *basicAllocator=0)
Definition bslmt_entrypointfunctoradapter.h:395
Definition bslmt_entrypointfunctoradapter.h:221