BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_function_rep.h
Go to the documentation of this file.
1/// @file bslstl_function_rep.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_function_rep.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_FUNCTION_REP
9#define INCLUDED_BSLSTL_FUNCTION_REP
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_function_rep bslstl_function_rep
15/// @brief Provide a non-template, common implementation for `bsl::function`.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_function_rep
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_function_rep-purpose"> Purpose</a>
25/// * <a href="#bslstl_function_rep-classes"> Classes </a>
26/// * <a href="#bslstl_function_rep-description"> Description </a>
27///
28/// # Purpose {#bslstl_function_rep-purpose}
29/// Provide a non-template, common implementation for `bsl::function`.
30///
31/// # Classes {#bslstl_function_rep-classes}
32///
33/// - bslstl::Function_Rep: Representation of a `bsl::function` object
34///
35/// @see bslstl_function
36///
37/// # Description {#bslstl_function_rep-description}
38/// This private, subordinate component to @ref bslstl_function
39/// provides a non-template class, `Function_Rep`, that is the data
40/// representation of `bsl::function` (see @ref bslstl_function ). The
41/// `bsl::function` class template uses `bslstl::Function_Rep` to store the
42/// callable held by the `function` (its *target*), the allocator, and a pointer
43/// to the function it uses to indirectly invoke the target (the *invoker*
44/// function).
45///
46/// The client of this component, `bsl::function`, is a complex class that is
47/// templated in two ways:
48///
49/// 1. The class itself has a template parameter representing the prototype
50/// (argument and return types) of its call operator. E.g.,
51/// type `bsl::function<int(char*)>` has member `int operator()(char*);`.
52/// 2. Several of its constructors are templated on a callable type and wrap an
53/// object of that type. By using type erasure, the type of the wrapped
54/// target is not part of the type of the `bsl::function`.
55///
56/// The `Function_Rep` class takes care of the runtime polymorphism required by
57/// (2), above. It stores the target object (which can be of any size), copy-
58/// or move-constructs it, destroys it, and returns its runtime type, size, and
59/// address. Nothing in `Function_Rep` is concerned with the call prototype.
60///
61/// `Function_Rep` is a quasi-value-semantic type: It doesn't provide copy and
62/// move constructors or assignment operators, but it does have the abstract
63/// notion of an in-memory value (the target object, if not empty) and it
64/// provides methods for copying, moving, swapping, and destroying that value.
65/// There is no ability to provide equality comparison because the wrapped
66/// object is not required to provide equality comparison operations.
67///
68/// `Function_Rep` has only one constructor, which creates an empty object (one
69/// with no target) using a specified allocator. The methods of `Function_Rep`
70/// are a collection of primitive operations for setting, getting, copy
71/// constructing, move constructing, or swapping the target object, as well as
72/// accessing the allocator and invoker function pointer. The methods to set
73/// and get the invoker pointer represent it as a generic function pointer (the
74/// closest we could get to `void *` for function pointers), so it is up to the
75/// caller to cast the pointer back to a specific function pointer type before
76/// invoking it.
77/// @}
78/** @} */
79/** @} */
80
81/** @addtogroup bsl
82 * @{
83 */
84/** @addtogroup bslstl
85 * @{
86 */
87/** @addtogroup bslstl_function_rep
88 * @{
89 */
90
91#include <bslscm_version.h>
92
94
96#include <bslma_bslallocator.h>
97
98#include <bslmf_assert.h>
99#include <bslmf_decay.h>
100#include <bslmf_util.h> // 'forward(V)'
101
102#include <bsls_assert.h>
104#include <bsls_platform.h>
105#include <bsls_util.h> // 'forward<T>(V)'
106
108
109#include <cstddef>
110#include <cstdlib>
111#include <typeinfo>
112
113
114namespace bslstl {
115
116 // ==================
117 // class Function_Rep
118 // ==================
119
120/// This is a component-private class. Do not use.
121///
122/// This class provides a non-template representation for a `bsl::function`
123/// instance. It handles all of the object-management parts of
124/// `bsl::function` that are not specific to the prototype (argument list
125/// and return type), e.g., storing, copying, and moving the `function`
126/// object, but not invoking the `function` (which requires knowledge of the
127/// prototype). These management methods are run-time polymorphic, and
128/// therefore do not require that this class be a template (although several
129/// of the member functions are templates).
130///
131/// See @ref bslstl_function_rep
133
134 // PRIVATE CONSTANTS
135#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
136 public:
137 // Not really public: made public to work around a Sun compiler bug.
138#endif
139 static const std::size_t k_NON_SOO_SMALL_SIZE =
141
142 private:
143 // PRIVATE TYPES
144
145 /// Function manager opcode enumerators. See documentation for the
146 /// `functionManager` function template (below).
147 enum ManagerOpCode {
148
149 e_MOVE_CONSTRUCT ,
150 e_COPY_CONSTRUCT ,
151 e_DESTROY ,
152 e_DESTRUCTIVE_MOVE,
153 e_GET_SIZE ,
154 e_GET_TARGET ,
155 e_GET_TYPE_ID
156 };
157
158 /// This union stores either a pointer or a `size_t`. It is used as
159 /// the return type for the manager function (below).
160 union ManagerRet {
161
162 private:
163 // DATA
164 std::size_t d_asSize_t;
165 void *d_asPtr_p;
166
167 public:
168 // CREATORS
169
170 /// Create a union holding the specified `s` `size_t`.
171 ManagerRet(std::size_t s); // IMPLICIT
172
173 /// Create a union holding the specified `p` pointer.
174 ManagerRet(void *p); // IMPLICIT
175
176 // ACCESSORS
177
178 /// Return the `size_t` stored in this union.
179 ///
180 /// \pre The behavior is undefined unless this object was constructed with a `size_t`.
181 operator std::size_t() const;
182
183 /// Return the pointer stored in this union.
184 ///
185 /// \pre The behavior is undefined unless this object was constructed with a `TP *`.
186 template <class TP>
187 operator TP *() const;
188 };
189
190 /// Abbreviation for metafunction used to provide a C++03-compatible
191 /// implementation of `std::decay` that treats `bslmf::MovableReference`
192 /// as an rvalue reference.
193 template <class TYPE>
194 struct Decay
195 : bsl::decay<typename bslmf::MovableRefUtil::RemoveReference<TYPE>::type> {
196 };
197
200
201 /// Type aliases for convenience.
203
204 // DATA
205
206 /// When wrapping a target object that qualifies for the small-object
207 /// optimization (as described in the
208 /// @ref bslstl_function_smallobjectoptimization component), this buffer
209 /// stores the in-place representation of the target; otherwise it
210 /// stores a pointer to allocated storage holding the target.
211 mutable InplaceBuffer d_objbuf;
212
213 /// Allocator used to supply memory
214 bsl::allocator<char> d_allocator;
215
216 /// Pointer to a specialization of the `functionManager` function
217 /// template (below) used to manage the current target, or null for
218 /// empty objects.
219 ManagerRet (*d_funcManager_p)(ManagerOpCode opCode,
220 Function_Rep *rep_p,
221 void *srcFunc_vp);
222
223 /// Pointer to the function used to invoke the current target, or null for empty objects.
224 ///
225 /// \note Note that this pointer is always set *after*
226 /// `d_funcManager_p` (see state transition table, below).
227 void (*d_invoker_p)();
228
229 // The table below shows progression of states of the a `Function_Rep` from
230 // empty through having a fully constructed target. The progression goes
231 // in the reverse direction when setting the `Function_Rep` back to empty.
232 // The "target allocated" state is transient and occurs only while a target
233 // is being installed; unless otherwise documented, all member functions
234 // assume as a class invariant that an object is not in the "target
235 // allocated" state. This state *can* exist at destruction during
236 // exception unwinding and is specifically handled correctly by the
237 // destructor.
238 //
239 // d_funcManager_p d_invoker_p Rep (d_objbuf) state
240 // =============== =========== ======================================
241 // NULL NULL Initial (Empty)
242 // non-NULL NULL Target allocated (transient)
243 // non-NULL non-NULL Target constructed
244
245 // PRIVATE CLASS METHODS
246
247 /// Apply the specified `opCode` to the objects at the specified `rep`
248 /// and `srcVoidPtr` addresses and return a pointer or `size_t` result.
249 /// If `srcVoidPtr` is non-null, it should point to a callable object of
250 /// type indicated by template parameter `FUNC`. A pointer to an
251 /// instantiation of this function is stored in `d_functionManager_p`
252 /// and is used to manage the target object wrapped in a `Function_Rep`.
253 /// The `FUNC` parameter must not be wrapped in a
254 /// `NothrowMovableWrapper`. The `INPLACE` parameter should be `true`
255 /// if and only if the target is allocated inplace within `*rep`.
256 ///
257 /// The following describes the behavior of each possible value for
258 /// `opCode`. In this description, *the* *target* refers to the object
259 /// wrapped within the representation at `rep`.
260 ///
261 ///: `e_MOVE_CONSTRUCT`:
262 ///: Move construct the target from the callable object at
263 ///: `srcVoidPtr`. Return the number of bytes needed to hold the
264 ///: object. The behavior is undefined unless memory has been
265 ///: allocated for the target.
266 ///:
267 ///: `e_COPY_CONSTRUCT`:
268 ///: Copy construct the target from the callable object at
269 ///: `srcVoidPtr`. Return the number of bytes needed to hold the
270 ///: object. The behavior is undefined unless memory has been
271 ///: allocated for the target.
272 ///:
273 ///: `e_DESTROY`:
274 ///: Call the destructor for the target object but do not deallocate
275 ///: it. Return the number of bytes needed to hold the destroyed
276 ///: object. The behavior is undefined unless `*rep` holds a target
277 ///: of type `FUNC`.
278 ///:
279 ///: `e_DESTRUCTIVE_MOVE`:
280 ///: Move the object at `srcVoidPtr` to the memory allocated for the
281 ///: target and destroy the object at `srcVoidPtr`. Return the number
282 ///: of bytes needed to hold the target. This operation is
283 ///: guaranteed not to throw. If `FUNC` is bitwise movable, perform
284 ///: this move using `memcpy`; otherwise invoke the move constructor
285 ///: followed by the destructor. The behavior is undefined unless
286 ///: memory has been allocated for the target. Note that this
287 ///: operation is never invoked unless `FUNC` has either the
288 ///: `bslmf::BitwiseMoveable` or `bsl::is_nothrow_move_constructible`
289 ///: trait. If `bsl::is_nothrow_move_constructible<FUNC>` is true but
290 ///: the move constructor throws anyway, the program is likely to
291 ///: terminate.
292 ///:
293 ///: `e_GET_SIZE`:
294 ///: Return the size of a target object of type `FUNC`, encoded using
295 ///: the rules of the `Soo::SooFuncSize` metafunction (see
296 ///: {@ref bslstl_function_smallobjectoptimization }). The arguments
297 ///: `rep` and `srcVoidPtr` are not used.
298 ///:
299 ///: `e_GET_TARGET`:
300 ///: If the `srcVoidPtr` argument points to `typeid(FUNC)` return a
301 ///: pointer to the target object; otherwise return a null pointer.
302 ///: The behavior is undefined unless `*rep` holds a target of type
303 ///: `FUNC` and `srcVoidPtr` points to a valid `type_info` object.
304 ///:
305 ///: `e_GET_TYPE_ID`:
306 ///: Return a pointer to the `type_info` for a target object of type
307 ///: `FUNC`. The `srcVoidPtr` argument is not used.
308 ///
309 /// Implementation note: Instantiations of this function implement a
310 /// kind of hand-coded virtual-function dispatch. Internally, a
311 /// `Manager` function uses a `switch` statement rather than performing
312 /// a virtual-table lookup. This mechanism was chosen because testing
313 /// showed that it saves a significant amount of generated code space
314 /// over the C++ virtual-function mechanism, especially when the number
315 /// of different instantiations of `bsl::function` is large.
316 template <class FUNC, bool INPLACE>
317 static ManagerRet functionManager(ManagerOpCode opCode,
318 Function_Rep *rep,
319 void *srcVoidPtr);
320
321 // PRIVATE MANIPULATORS
322
323 /// Initialize this object's `d_objbuf` field, allocating enough storage
324 /// to hold a target of the specified `sooFuncSize`, which is encoded as
325 /// per the `Soo::SooFuncSize` metafunction. If the function qualifies
326 /// for the small-object optimization, then the storage comes from the
327 /// small-object buffer in `d_objbuf`; otherwise it is obtained from
328 /// `d_allocator` and `d_objbuf.d_object_p` is set to the address of the
329 /// allocated block. The target object is not initialized, nor is
330 /// `d_funcManager_p` modified.
331 void allocateBuf(std::size_t sooFuncSize);
332
333 /// Copy the specified callable object `func` into this object's target
334 /// storage (either in-place within this object's small-object buffer or out-of-place from the allocator).
335 ///
336 /// \pre The behavior is undefined unless
337 /// this object is in the target-allocated state for the `func`; which
338 /// is when `d_invoker_p == 0` and `d_funcManager_p != 0`.
339 template <class FUNC>
340 void constructTarget(FUNC& func);
341 template <class FUNC>
342 void constructTarget(BSLMF_MOVABLEREF_DEDUCE(const FUNC) func);
343
344 /// Move the specified callable object `func` into this object's target
345 /// storage (either in-place within this object's small-object buffer or out-of-place from the allocator).
346 ///
347 /// \pre The behavior is undefined unless
348 /// this object is in the target-allocated state for the `func`; which
349 /// is when `d_invoker_p == 0` and `d_funcManager_p != 0`.
350 template <class FUNC>
351 void constructTarget(BSLMF_MOVABLEREF_DEDUCE(FUNC) func);
352
353 // PRIVATE ACCESSORS
354
355 /// Return the size of the target, encoded as per the `Soo::SooFuncSize`
356 /// metafunction, or zero if this `function` is empty.
357 std::size_t calcSooFuncSize() const BSLS_KEYWORD_NOEXCEPT;
358
359 private:
360 // NOT IMPLEMENTED
362 Function_Rep& operator=(const Function_Rep&);
363
364 public:
365 // TYPES
366
367 /// This class does not conform to any specific interface so is not
368 /// allocator-aware in the strict sense. However, this type does hold
369 /// an allocator for its AA client and therefore uses the type name
370 /// for the allocator preferred by AA types.
372
373 /// A "generic" function type analogous to the data type `void` (though
374 /// without the language support provided by `void`).
375 typedef void GenericInvoker();
376
377 // CREATORS
378
379 /// Create an empty object using the specified `allocator` to supply
380 /// memory.
381 explicit Function_Rep(const allocator_type& allocator)
383
384 /// Destroy this object and its target object (if any) and deallocate
385 /// memory for the target object (if not in-place). This destructor
386 /// is implemented to correctly deallocate a target object that has been
387 /// allocated but not constructed (e.g., if an exception is thrown
388 /// while constructing the target).
390
391 // MANIPULATORS
392
393 /// Copy-initialize this rep from the specified `original` rep. If an
394 /// exception is thrown by the copy, the only valid subsequent operation on this object is destruction.
395 ///
396 /// \pre The behavior is undefined unless
397 /// this object is empty before the call.
398 void copyInit(const Function_Rep& original);
399
400 /// Do nothing if the specified `func` is a null pointer, otherwise
401 /// allocate storage (either in-place within this object's small-object
402 /// buffer or out-of-place from the allocator) to hold a target of
403 /// (template parameter) type `FUNC`, forward the `func` to the
404 /// constructor of the new target, set `d_funcManager_p` to manage the
405 /// new target, and set `d_invoker_p` to the specified `invoker` address.
406 ///
407 /// \pre The behavior is undefined unless this object is empty on entry.
408 ///
409 /// \note Note that `FUNC` will not qualify for the small-object
410 /// optimization unless
411 /// `bsl::is_nothrow_move_constructible<FUNC>::value` is `true`.
412 template <class FUNC>
415
416 /// Change this object to be an empty object without changing its
417 /// allocator. Any previous target is destroyed and deallocated.
418 ///
419 /// \note Note that value returned by `get_allocator().mechanism()` might change,
420 /// but will point to an allocator with the same type managing the same
421 /// memory resource.
422 void makeEmpty();
423
424 /// Move-initialize this rep from the rep at the specified `from`
425 /// address, leaving the latter empty. If 'this->get_allocator() !=
426 /// from->get_allocator()', this function degenerates to a call to `copyInit(*from)`.
427 ///
428 /// \pre The behavior is undefined unless this rep is
429 /// empty before the call.
431
432 /// Exchange this object's target object, manager function, and invoker
433 /// with those of the specified `other` object.
434 ///
435 /// \pre The behavior is undefined unless `this->get_allocator() == other->get_allocator()`.
437
438 /// If `typeid(TP) == this->target_type()`, return a pointer offering
439 /// modifiable access to this object's target; otherwise return a null pointer.
440 ///
441 /// \note Note that this function is `const` but returns a
442 /// non-`const` pointer because, according to the C++ Standard,
443 /// `function` (and therefore this representation) does not adhere to
444 /// logical constness conventions.
445 template<class TP> TP* target() const BSLS_KEYWORD_NOEXCEPT;
446
447 /// Return a pointer offering modifiable access to this object's target.
448 /// If `INPLACE` is true, then the object is assumed to be allocated inplace in the small object buffer.
449 ///
450 /// \note Note that this function is
451 /// `const` but returns a non-`const` pointer because this type does not
452 /// adhere to logical constness conventions.
453 ///
454 /// \pre The behavior is undefined unless `typeid(TP) == this->target_type()` and `INPLACE` correctly
455 /// identifies whether the target is inplace.
456 template<class TP, bool INPLACE> TP* targetRaw() const
458
459 // ACCESSORS
460
461 /// Return the allocator used to supply memory for this object.
463
464 /// Return a pointer the invoker function set using `installFunc` or a
465 /// null pointer if this object is empty.
467
468 /// Return `true` if `invoker()` is a null pointer, indicating that this
469 /// object has no target object.
470 bool isEmpty() const BSLS_KEYWORD_NOEXCEPT;
471
472 /// The `isInplace` function is public in BDE legacy mode and private
473 /// otherwise.
474#ifdef BDE_OMIT_INTERNAL_DEPRECATED
475 private:
476#endif
477 /// Return `true` if the target is allocated in place within the
478 /// small-object buffer of this object; otherwise return `false`.
480
481 public:
482 /// Return a reference to the `type_info` for the type of the current
483 /// target object or `typeid(void)` if this object is empty. If the
484 /// target type is a specialization of `bslalg::NothrowMovableWrapper`,
485 /// then the returned `type_info` is for the unwrapped type.
486 const std::type_info& target_type() const BSLS_KEYWORD_NOEXCEPT;
487};
488
489} // close package namespace
490
491// ============================================================================
492// TEMPLATE AND INLINE FUNCTION IMPLEMENTATIONS
493// ============================================================================
494
495 // --------------------------------------
496 // class bslstl::Function_Rep::ManagerRet
497 // --------------------------------------
498
499// CREATORS
500inline
501bslstl::Function_Rep::ManagerRet::ManagerRet(std::size_t s)
502 : d_asSize_t(s)
503{
504}
505
506inline
508 : d_asPtr_p(p)
509{
510}
511
512// ACCESSORS
513inline
514bslstl::Function_Rep::ManagerRet::operator std::size_t() const
515{
516 return d_asSize_t;
517}
518
519template <class TP>
520inline
521bslstl::Function_Rep::ManagerRet::operator TP *() const
522{
523 return static_cast<TP*>(d_asPtr_p);
524}
525
526 // --------------------------
527 // class bslstl::Function_Rep
528 // --------------------------
529
530// PRIVATE CLASS METHODS
531template <class FUNC, bool INPLACE>
532bslstl::Function_Rep::ManagerRet
533bslstl::Function_Rep::functionManager(ManagerOpCode opCode,
534 Function_Rep *rep,
535 void *srcVoidPtr)
536{
538
539 // Assert that 'FUNC' is not wrapped. It should have been unwrapped before
540 // instantiating this template.
542
543 // If 'FUNC' was allocated inplace despite having a throwing move
544 // constructor, then 'INPLACE' will disagree with 'Soo::IsInplaceFunc'. In
545 // this case, use the raw size of 'FUNC' rather than the encoded size from
546 // 'Soo'.
547 static const std::size_t k_SOO_FUNC_SIZE =
548 (INPLACE && ! Soo::IsInplaceFunc<FUNC>::value) ?
549 sizeof(FUNC) : Soo::SooFuncSize<FUNC>::value;
550
551 // If a function manager exists, then target must have non-zero size.
552 BSLMF_ASSERT(0 != k_SOO_FUNC_SIZE);
553
554 FUNC *target = rep->targetRaw<FUNC, INPLACE>();
555
556 switch (opCode) {
557
558 case e_MOVE_CONSTRUCT: {
559 // Move-construct function object. There is no point to optimizing
560 // this operation for trivially movable types. If the type is
561 // trivially moveable, then the 'construct' operation below will do it
562 // trivially.
563 FUNC& original = *static_cast<FUNC *>(srcVoidPtr);
564 ConstructionUtil::construct(target,
565 rep->d_allocator,
567 } break;
568
569 case e_COPY_CONSTRUCT: {
570 // Copy-construct function object. There is no point to optimizing
571 // this operation for bitwise copyable types. If the type is trivially
572 // copyable, then the 'construct' operation below will do it trivially.
573 const FUNC& original = *static_cast<FUNC *>(srcVoidPtr);
574 ConstructionUtil::construct(target, rep->d_allocator, original);
575 } break;
576
577 case e_DESTROY: {
578 target->~FUNC();
579 } break;
580
581 case e_DESTRUCTIVE_MOVE: {
582 FUNC *fromPtr = static_cast<FUNC*>(srcVoidPtr);
583 ConstructionUtil::destructiveMove(target, rep->d_allocator, fromPtr);
584 } break;
585
586 case e_GET_SIZE: {
587 return k_SOO_FUNC_SIZE; // RETURN
588 }
589
590 case e_GET_TARGET: {
591 std::type_info *expType = static_cast<std::type_info *>(srcVoidPtr);
592 if (*expType != typeid(FUNC)) {
593 // Wrapped type does not match expected type.
594 return static_cast<FUNC*>(0); // RETURN
595 }
596 return target; // RETURN
597 }
598
599 case e_GET_TYPE_ID: {
600 // 'const_cast' needed for conversion to 'ManagerRet'.
601 return const_cast<std::type_info*>(&typeid(FUNC)); // RETURN
602 }
603 } // end switch
604
605 // Any case that doesn't return something explicitly, returns the size of
606 // the target object by default.
607 return k_SOO_FUNC_SIZE;
608}
609
610// PRIVATE MANIPULATORS
611template <class FUNC>
612void bslstl::Function_Rep::constructTarget(FUNC& func)
613{
614 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
615 BSLS_ASSERT_SAFE(0 == d_invoker_p);
616
617 typedef typename Decay<FUNC>::type DecayedFunc;
618 const DecayedFunc& decayedFunc = func;
619
620 typedef bslalg::NothrowMovableUtil NMUtil;
621 typedef typename NMUtil::UnwrappedType<DecayedFunc>::type UnwrappedFunc;
622 const UnwrappedFunc& unwrappedFunc = NMUtil::unwrap(decayedFunc);
623
624 d_funcManager_p(
625 e_COPY_CONSTRUCT, this, &const_cast<UnwrappedFunc&>(unwrappedFunc));
626}
627
628template <class FUNC>
629void bslstl::Function_Rep::constructTarget(BSLMF_MOVABLEREF_DEDUCE(const FUNC)
630 func)
631{
632 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
633 BSLS_ASSERT_SAFE(0 == d_invoker_p);
634
635 constructTarget(bslmf::MovableRefUtil::access(func));
636}
637
638template <class FUNC>
639void bslstl::Function_Rep::constructTarget(BSLMF_MOVABLEREF_DEDUCE(FUNC) func)
640{
641 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
642 BSLS_ASSERT_SAFE(0 == d_invoker_p);
643
644 typedef typename Decay<FUNC>::type DecayedFunc;
645 DecayedFunc& decayedFunc = func;
646
647 typedef bslalg::NothrowMovableUtil NMUtil;
648 typedef typename NMUtil::UnwrappedType<DecayedFunc>::type UnwrappedFunc;
649 UnwrappedFunc& unwrappedFunc = NMUtil::unwrap(decayedFunc);
650
651 d_funcManager_p(e_MOVE_CONSTRUCT, this, &unwrappedFunc);
652}
653
654// PRIVATE ACCESSORS
655inline
656std::size_t bslstl::Function_Rep::calcSooFuncSize() const BSLS_KEYWORD_NOEXCEPT
657{
658 std::size_t ret = 0;
659
660 if (d_funcManager_p) {
661 ret = d_funcManager_p(e_GET_SIZE,
662 const_cast<Function_Rep*>(this), 0);
663 }
664
665 return ret;
666}
667
668// CREATORS
669inline
670bslstl::Function_Rep::Function_Rep(const allocator_type& allocator)
672 : d_allocator(allocator)
673 , d_funcManager_p(0)
674 , d_invoker_p(0)
675{
676}
677
678// MANIPULATORS
679template <class FUNC>
683{
684 if (! invoker) {
685 // Leave this object in the empty state.
686 return; // RETURN
687 }
688
689 typedef typename Decay<FUNC>::type DecayedFunc;
690
691 // If 'FUNC' is wrapped in a 'bslalg::NothrowMovableWrapper', then the SOO
692 // size calculation works as though 'FUNC' were nothrow movable.
693 static const std::size_t k_SOO_FUNC_SIZE =
695 static const bool k_INPLACE = Soo::IsInplaceFunc<DecayedFunc>::value;
696
697 allocateBuf(k_SOO_FUNC_SIZE); // Might throw
698
699 // Target rep was successfully allocated, set 'd_funcManager_p'. If 'FUNC'
700 // is wrapped in a 'NothrowMovableWrapper', then unwrap it first, but use
701 // 'k_INPLACE' value for the original (potentially-wrapped) 'FUNC' so that
702 // the function manager knows whether to expect the object to be inplace or
703 // not.
704 typedef
706 UnwrappedFunc;
707 d_funcManager_p = &functionManager<UnwrappedFunc, k_INPLACE>;
708
709 // Copy or move the function argument into '*this' object. Note that this
710 // operation might throw.
711 constructTarget(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
712
713 // Exception danger has passed. Setting the invoker makes the
714 // 'Function_Rep' non-empty.
715 d_invoker_p = invoker;
716}
717
718template <class TP>
719inline
721{
722 if (! d_funcManager_p) {
723 return 0; // RETURN
724 }
725
726 const std::type_info& tpTypeInfo = typeid(TP);
727
728 void *ret = d_funcManager_p(e_GET_TARGET,
729 const_cast<Function_Rep *>(this),
730 const_cast<std::type_info*>(&tpTypeInfo));
731
732 // If 'TP' is a function (not pointer-to-function) type, 'ret' will be
733 // null, but we still must use a C-style cast to avoid the compiler error
734 // produced from converting a data pointer to a function pointer.
735 return (TP *) ret;
736}
737
738template <class TP, bool INPLACE>
739inline
741{
742 // If target fits in 'd_objbuf', then it is inplace; otherwise, its
743 // heap-allocated address is found in 'd_objbuf.d_object_p'. There is no
744 // need to dispatch using metaprogramming because the compiler will
745 // optimize away the compile-time conditional test.
746 return static_cast<TP*>(INPLACE ? &d_objbuf : d_objbuf.d_object_p);
747}
748
749// ACCESSORS
750inline
753{
754 return d_allocator;
755}
756
757inline
760{
761 return d_invoker_p;
762}
763
764inline
766{
767 return 0 == d_invoker_p;
768}
769
770
771
772#endif // ! defined(INCLUDED_BSLSTL_FUNCTION_REP)
773
774// ----------------------------------------------------------------------------
775// Copyright 2020 Bloomberg Finance L.P.
776//
777// Licensed under the Apache License, Version 2.0 (the "License");
778// you may not use this file except in compliance with the License.
779// You may obtain a copy of the License at
780//
781// http://www.apache.org/licenses/LICENSE-2.0
782//
783// Unless required by applicable law or agreed to in writing, software
784// distributed under the License is distributed on an "AS IS" BASIS,
785// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
786// See the License for the specific language governing permissions and
787// limitations under the License.
788// ----------------------------- END-OF-FILE ----------------------------------
789
790/** @} */
791/** @} */
792/** @} */
Definition bslma_bslallocator.h:588
Definition bslmf_decay.h:158
decay_imp< U, k_ISARRAY, k_ISFUNC >::type type
Definition bslmf_decay.h:167
Definition bslma_allocator.h:545
Definition bslstl_function_rep.h:132
void swap(Function_Rep &other) BSLS_KEYWORD_NOEXCEPT
const std::type_info & target_type() const BSLS_KEYWORD_NOEXCEPT
void GenericInvoker()
Definition bslstl_function_rep.h:375
bool isInplace() const BSLS_KEYWORD_NOEXCEPT
void copyInit(const Function_Rep &original)
void moveInit(Function_Rep *from)
bsl::allocator< char > allocator_type
Definition bslstl_function_rep.h:371
Definition bslstl_function_smallobjectoptimization.h:170
Definition bslstl_function_smallobjectoptimization.h:78
static const std::size_t k_NON_SOO_SMALL_SIZE
Definition bslstl_function_smallobjectoptimization.h:142
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLMF_MOVABLEREF_DEDUCE(...)
Definition bslmf_movableref.h:691
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used to supply memory for this object.
Definition bslstl_function_rep.h:752
void installFunc(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func, GenericInvoker invoker)
Definition bslstl_function_rep.h:680
bool isEmpty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:765
TP * targetRaw() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:740
ManagerRet(std::size_t s)
Create a union holding the specified s size_t.
Definition bslstl_function_rep.h:501
GenericInvoker * invoker() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:759
TP * target() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:720
Definition bslstl_algorithm.h:84
Definition bdldfp_decimal.h:5549
Definition bslalg_nothrowmovableutil.h:353
NothrowMovableUtil_Traits< TYPE >::UnwrappedType type
Definition bslalg_nothrowmovableutil.h:376
Definition bslalg_nothrowmovableutil.h:346
Definition bslma_constructionutil.h:731
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039
Definition bslstl_function_smallobjectoptimization.h:113
void * d_object_p
Definition bslstl_function_smallobjectoptimization.h:116