BDE 4.14.0 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. The behavior is
179 /// undefined unless this object was constructed with a `size_t`.
180 operator std::size_t() const;
181
182 /// Return the pointer stored in this union. The behavior is
183 /// undefined unless this object was constructed with a `TP *`.
184 template <class TP>
185 operator TP *() const;
186 };
187
188 /// Abbreviation for metafunction used to provide a C++03-compatible
189 /// implementation of `std::decay` that treats `bslmf::MovableReference`
190 /// as an rvalue reference.
191 template <class TYPE>
192 struct Decay
193 : bsl::decay<typename bslmf::MovableRefUtil::RemoveReference<TYPE>::type> {
194 };
195
198
199 /// Type aliases for convenience.
201
202 // DATA
203
204 /// When wrapping a target object that qualifies for the small-object
205 /// optimization (as described in the
206 /// `bslstl_function_smallobjectoptimization` component), this buffer
207 /// stores the in-place representation of the target; otherwise it
208 /// stores a pointer to allocated storage holding the target.
209 mutable InplaceBuffer d_objbuf;
210
211 /// Allocator used to supply memory
212 bsl::allocator<char> d_allocator;
213
214 /// Pointer to a specialization of the `functionManager` function
215 /// template (below) used to manage the current target, or null for
216 /// empty objects.
217 ManagerRet (*d_funcManager_p)(ManagerOpCode opCode,
218 Function_Rep *rep_p,
219 void *srcFunc_vp);
220
221 /// Pointer to the function used to invoke the current target, or null
222 /// for empty objects. Note that this pointer is always set *after*
223 /// `d_funcManager_p` (see state transition table, below).
224 void (*d_invoker_p)();
225
226 // The table below shows progression of states of the a `Function_Rep` from
227 // empty through having a fully constructed target. The progression goes
228 // in the reverse direction when setting the `Function_Rep` back to empty.
229 // The "target allocated" state is transient and occurs only while a target
230 // is being installed; unless otherwise documented, all member functions
231 // assume as a class invariant that an object is not in the "target
232 // allocated" state. This state *can* exist at destruction during
233 // exception unwinding and is specifically handled correctly by the
234 // destructor.
235 //
236 // d_funcManager_p d_invoker_p Rep (d_objbuf) state
237 // =============== =========== ======================================
238 // NULL NULL Initial (Empty)
239 // non-NULL NULL Target allocated (transient)
240 // non-NULL non-NULL Target constructed
241
242 // PRIVATE CLASS METHODS
243
244 /// Apply the specified `opCode` to the objects at the specified `rep`
245 /// and `srcVoidPtr` addresses and return a pointer or `size_t` result.
246 /// If `srcVoidPtr` is non-null, it should point to a callable object of
247 /// type indicated by template parameter `FUNC`. A pointer to an
248 /// instantiation of this function is stored in `d_functionManager_p`
249 /// and is used to manage the target object wrapped in a `Function_Rep`.
250 /// The `FUNC` parameter must not be wrapped in a
251 /// `NothrowMovableWrapper`. The `INPLACE` parameter should be `true`
252 /// if and only if the target is allocated inplace within `*rep`.
253 ///
254 /// The following describes the behavior of each possible value for
255 /// `opCode`. In this description, *the* *target* refers to the object
256 /// wrapped within the representation at `rep`.
257 ///
258 ///: `e_MOVE_CONSTRUCT`:
259 ///: Move construct the target from the callable object at
260 ///: `srcVoidPtr`. Return the number of bytes needed to hold the
261 ///: object. The behavior is undefined unless memory has been
262 ///: allocated for the target.
263 ///:
264 ///: `e_COPY_CONSTRUCT`:
265 ///: Copy construct the target from the callable object at
266 ///: `srcVoidPtr`. Return the number of bytes needed to hold the
267 ///: object. The behavior is undefined unless memory has been
268 ///: allocated for the target.
269 ///:
270 ///: `e_DESTROY`:
271 ///: Call the destructor for the target object but do not deallocate
272 ///: it. Return the number of bytes needed to hold the destroyed
273 ///: object. The behavior is undefined unless `*rep` holds a target
274 ///: of type `FUNC`.
275 ///:
276 ///: `e_DESTRUCTIVE_MOVE`:
277 ///: Move the object at `srcVoidPtr` to the memory allocated for the
278 ///: target and destroy the object at `srcVoidPtr`. Return the number
279 ///: of bytes needed to hold the target. This operation is
280 ///: guaranteed not to throw. If `FUNC` is bitwise movable, perform
281 ///: this move using `memcpy`; otherwise invoke the move constructor
282 ///: followed by the destructor. The behavior is undefined unless
283 ///: memory has been allocated for the target. Note that this
284 ///: operation is never invoked unless `FUNC` has either the
285 ///: `bslmf::BitwiseMoveable` or `bsl::is_nothrow_move_constructible`
286 ///: trait. If `bsl::is_nothrow_move_constructible<FUNC>` is true but
287 ///: the move constructor throws anyway, the program is likely to
288 ///: terminate.
289 ///:
290 ///: `e_GET_SIZE`:
291 ///: Return the size of a target object of type `FUNC`, encoded using
292 ///: the rules of the `Soo::SooFuncSize` metafunction (see
293 ///: {`bslstl_function_smallobjectoptimization`}). The arguments
294 ///: `rep` and `srcVoidPtr` are not used.
295 ///:
296 ///: `e_GET_TARGET`:
297 ///: If the `srcVoidPtr` argument points to `typeid(FUNC)` return a
298 ///: pointer to the target object; otherwise return a null pointer.
299 ///: The behavior is undefined unless `*rep` holds a target of type
300 ///: `FUNC` and `srcVoidPtr` points to a valid `type_info` object.
301 ///:
302 ///: `e_GET_TYPE_ID`:
303 ///: Return a pointer to the `type_info` for a target object of type
304 ///: `FUNC`. The `srcVoidPtr` argument is not used.
305 ///
306 /// Implementation note: Instantiations of this function implement a
307 /// kind of hand-coded virtual-function dispatch. Internally, a
308 /// `Manager` function uses a `switch` statement rather than performing
309 /// a virtual-table lookup. This mechanism was chosen because testing
310 /// showed that it saves a significant amount of generated code space
311 /// over the C++ virtual-function mechanism, especially when the number
312 /// of different instantiations of `bsl::function` is large.
313 template <class FUNC, bool INPLACE>
314 static ManagerRet functionManager(ManagerOpCode opCode,
315 Function_Rep *rep,
316 void *srcVoidPtr);
317
318 // PRIVATE MANIPULATORS
319
320 /// Initialize this object's `d_objbuf` field, allocating enough storage
321 /// to hold a target of the specified `sooFuncSize`, which is encoded as
322 /// per the `Soo::SooFuncSize` metafunction. If the function qualifies
323 /// for the small-object optimization, then the storage comes from the
324 /// small-object buffer in `d_objbuf`; otherwise it is obtained from
325 /// `d_allocator` and `d_objbuf.d_object_p` is set to the address of the
326 /// allocated block. The target object is not initialized, nor is
327 /// `d_funcManager_p` modified.
328 void allocateBuf(std::size_t sooFuncSize);
329
330 /// Copy the specified callable object `func` into this object's target
331 /// storage (either in-place within this object's small-object buffer or
332 /// out-of-place from the allocator). The behavior is undefined unless
333 /// this object is in the target-allocated state for the `func`; which
334 /// is when `d_invoker_p == 0` and `d_funcManager_p != 0`.
335 template <class FUNC>
336 void constructTarget(FUNC& func);
337 template <class FUNC>
338 void constructTarget(BSLMF_MOVABLEREF_DEDUCE(const FUNC) func);
339
340 /// Move the specified callable object `func` into this object's target
341 /// storage (either in-place within this object's small-object buffer or
342 /// out-of-place from the allocator). The behavior is undefined unless
343 /// this object is in the target-allocated state for the `func`; which
344 /// is when `d_invoker_p == 0` and `d_funcManager_p != 0`.
345 template <class FUNC>
346 void constructTarget(BSLMF_MOVABLEREF_DEDUCE(FUNC) func);
347
348 // PRIVATE ACCESSORS
349
350 /// Return the size of the target, encoded as per the `Soo::SooFuncSize`
351 /// metafunction, or zero if this `function` is empty.
352 std::size_t calcSooFuncSize() const BSLS_KEYWORD_NOEXCEPT;
353
354 // NOT IMPLEMENTED
356 Function_Rep& operator=(const Function_Rep&);
357
358 public:
359 // TYPES
360
361 /// This class does not conform to any specific interface so is not
362 /// allocator-aware in the strict sense. However, this type does hold
363 /// an allocator for its AA client and therefore uses the type name
364 /// for the allocator preferred by AA types.
366
367 /// A "generic" function type analogous to the data type `void` (though
368 /// without the language support provided by `void`).
369 typedef void GenericInvoker();
370
371 // CREATORS
372
373 /// Create an empty object using the specified `allocator` to supply
374 /// memory.
375 explicit Function_Rep(const allocator_type& allocator)
377
378 /// Destroy this object and its target object (if any) and deallocate
379 /// memory for the target object (if not in-place). This destructor
380 /// is implemented to correctly deallocate a target object that has been
381 /// allocated but not constructed (e.g., if an exception is thrown
382 /// while constructing the target).
384
385 // MANIPULATORS
386
387 /// Copy-initialize this rep from the specified `original` rep. If an
388 /// exception is thrown by the copy, the only valid subsequent operation
389 /// on this object is destruction. The behavior is undefined unless
390 /// this object is empty before the call.
391 void copyInit(const Function_Rep& original);
392
393 /// Do nothing if the specified `func` is a null pointer, otherwise
394 /// allocate storage (either in-place within this object's small-object
395 /// buffer or out-of-place from the allocator) to hold a target of
396 /// (template parameter) type `FUNC`, forward the `func` to the
397 /// constructor of the new target, set `d_funcManager_p` to manage the
398 /// new target, and set `d_invoker_p` to the specified `invoker`
399 /// address. The behavior is undefined unless this object is empty on
400 /// entry. Note that `FUNC` will not qualify for the small-object
401 /// optimization unless
402 /// `bsl::is_nothrow_move_constructible<FUNC>::value` is `true`.
403 template <class FUNC>
406
407 /// Change this object to be an empty object without changing its
408 /// allocator. Any previous target is destroyed and deallocated. Note
409 /// that value returned by `get_allocator().mechanism()` might change,
410 /// but will point to an allocator with the same type managing the same
411 /// memory resource.
412 void makeEmpty();
413
414 /// Move-initialize this rep from the rep at the specified `from`
415 /// address, leaving the latter empty. If 'this->get_allocator() !=
416 /// from->get_allocator()', this function degenerates to a call to
417 /// `copyInit(*from)`. The behavior is undefined unless this rep is
418 /// empty before the call.
420
421 /// Exchange this object's target object, manager function, and invoker
422 /// with those of the specified `other` object. The behavior is
423 /// undefined unless `this->get_allocator() == other->get_allocator()`.
425
426 /// If `typeid(TP) == this->target_type()`, return a pointer offering
427 /// modifiable access to this object's target; otherwise return a null
428 /// pointer. Note that this function is `const` but returns a
429 /// non-`const` pointer because, according to the C++ Standard,
430 /// `function` (and therefore this representation) does not adhere to
431 /// logical constness conventions.
432 template<class TP> TP* target() const BSLS_KEYWORD_NOEXCEPT;
433
434 /// Return a pointer offering modifiable access to this object's target.
435 /// If `INPLACE` is true, then the object is assumed to be allocated
436 /// inplace in the small object buffer. Note that this function is
437 /// `const` but returns a non-`const` pointer because this type does not
438 /// adhere to logical constness conventions. The behavior is undefined
439 /// unless `typeid(TP) == this->target_type()` and `INPLACE` correctly
440 /// identifies whether the target is inplace.
441 template<class TP, bool INPLACE> TP* targetRaw() const
443
444 // ACCESSORS
445
446 /// Return the allocator used to supply memory for this object.
448
449 /// Return a pointer the invoker function set using `installFunc` or a
450 /// null pointer if this object is empty.
452
453 /// Return `true` if `invoker()` is a null pointer, indicating that this
454 /// object has no target object.
455 bool isEmpty() const BSLS_KEYWORD_NOEXCEPT;
456
457 /// The `isInplace` function is public in BDE legacy mode and private
458 /// otherwise.
459#ifdef BDE_OMIT_INTERNAL_DEPRECATED
460 private:
461#endif
462 /// Return `true` if the target is allocated in place within the
463 /// small-object buffer of this object; otherwise return `false`.
465
466 public:
467 /// Return a reference to the `type_info` for the type of the current
468 /// target object or `typeid(void)` if this object is empty. If the
469 /// target type is a specialization of `bslalg::NothrowMovableWrapper`,
470 /// then the returned `type_info` is for the unwrapped type.
471 const std::type_info& target_type() const BSLS_KEYWORD_NOEXCEPT;
472};
473
474} // close package namespace
475
476// ============================================================================
477// TEMPLATE AND INLINE FUNCTION IMPLEMENTATIONS
478// ============================================================================
479
480 // --------------------------------------
481 // class bslstl::Function_Rep::ManagerRet
482 // --------------------------------------
483
484// CREATORS
485inline
486bslstl::Function_Rep::ManagerRet::ManagerRet(std::size_t s)
487 : d_asSize_t(s)
488{
489}
490
491inline
493 : d_asPtr_p(p)
494{
495}
496
497// ACCESSORS
498inline
499bslstl::Function_Rep::ManagerRet::operator std::size_t() const
500{
501 return d_asSize_t;
502}
503
504template <class TP>
505inline
506bslstl::Function_Rep::ManagerRet::operator TP *() const
507{
508 return static_cast<TP*>(d_asPtr_p);
509}
510
511 // --------------------------
512 // class bslstl::Function_Rep
513 // --------------------------
514
515// PRIVATE CLASS METHODS
516template <class FUNC, bool INPLACE>
517bslstl::Function_Rep::ManagerRet
518bslstl::Function_Rep::functionManager(ManagerOpCode opCode,
519 Function_Rep *rep,
520 void *srcVoidPtr)
521{
523
524 // Assert that 'FUNC' is not wrapped. It should have been unwrapped before
525 // instantiating this template.
527
528 // If 'FUNC' was allocated inplace despite having a throwing move
529 // constructor, then 'INPLACE' will disagree with 'Soo::IsInplaceFunc'. In
530 // this case, use the raw size of 'FUNC' rather than the encoded size from
531 // 'Soo'.
532 static const std::size_t k_SOO_FUNC_SIZE =
533 (INPLACE && ! Soo::IsInplaceFunc<FUNC>::value) ?
534 sizeof(FUNC) : Soo::SooFuncSize<FUNC>::value;
535
536 // If a function manager exists, then target must have non-zero size.
537 BSLMF_ASSERT(0 != k_SOO_FUNC_SIZE);
538
539 FUNC *target = rep->targetRaw<FUNC, INPLACE>();
540
541 switch (opCode) {
542
543 case e_MOVE_CONSTRUCT: {
544 // Move-construct function object. There is no point to optimizing
545 // this operation for trivially movable types. If the type is
546 // trivially moveable, then the 'construct' operation below will do it
547 // trivially.
548 FUNC& original = *static_cast<FUNC *>(srcVoidPtr);
549 ConstructionUtil::construct(target,
550 rep->d_allocator,
552 } break;
553
554 case e_COPY_CONSTRUCT: {
555 // Copy-construct function object. There is no point to optimizing
556 // this operation for bitwise copyable types. If the type is trivially
557 // copyable, then the 'construct' operation below will do it trivially.
558 const FUNC& original = *static_cast<FUNC *>(srcVoidPtr);
559 ConstructionUtil::construct(target, rep->d_allocator, original);
560 } break;
561
562 case e_DESTROY: {
563 target->~FUNC();
564 } break;
565
566 case e_DESTRUCTIVE_MOVE: {
567 FUNC *fromPtr = static_cast<FUNC*>(srcVoidPtr);
568 ConstructionUtil::destructiveMove(target, rep->d_allocator, fromPtr);
569 } break;
570
571 case e_GET_SIZE: {
572 return k_SOO_FUNC_SIZE; // RETURN
573 }
574
575 case e_GET_TARGET: {
576 std::type_info *expType = static_cast<std::type_info *>(srcVoidPtr);
577 if (*expType != typeid(FUNC)) {
578 // Wrapped type does not match expected type.
579 return static_cast<FUNC*>(0); // RETURN
580 }
581 return target; // RETURN
582 }
583
584 case e_GET_TYPE_ID: {
585 // 'const_cast' needed for conversion to 'ManagerRet'.
586 return const_cast<std::type_info*>(&typeid(FUNC)); // RETURN
587 }
588 } // end switch
589
590 // Any case that doesn't return something explicitly, returns the size of
591 // the target object by default.
592 return k_SOO_FUNC_SIZE;
593}
594
595// PRIVATE MANIPULATORS
596template <class FUNC>
597void bslstl::Function_Rep::constructTarget(FUNC& func)
598{
599 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
600 BSLS_ASSERT_SAFE(0 == d_invoker_p);
601
602 typedef typename Decay<FUNC>::type DecayedFunc;
603 const DecayedFunc& decayedFunc = func;
604
605 typedef bslalg::NothrowMovableUtil NMUtil;
606 typedef typename NMUtil::UnwrappedType<DecayedFunc>::type UnwrappedFunc;
607 const UnwrappedFunc& unwrappedFunc = NMUtil::unwrap(decayedFunc);
608
609 d_funcManager_p(
610 e_COPY_CONSTRUCT, this, &const_cast<UnwrappedFunc&>(unwrappedFunc));
611}
612
613template <class FUNC>
614void bslstl::Function_Rep::constructTarget(BSLMF_MOVABLEREF_DEDUCE(const FUNC)
615 func)
616{
617 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
618 BSLS_ASSERT_SAFE(0 == d_invoker_p);
619
620 constructTarget(bslmf::MovableRefUtil::access(func));
621}
622
623template <class FUNC>
624void bslstl::Function_Rep::constructTarget(BSLMF_MOVABLEREF_DEDUCE(FUNC) func)
625{
626 BSLS_ASSERT_SAFE(0 != d_funcManager_p);
627 BSLS_ASSERT_SAFE(0 == d_invoker_p);
628
629 typedef typename Decay<FUNC>::type DecayedFunc;
630 DecayedFunc& decayedFunc = func;
631
632 typedef bslalg::NothrowMovableUtil NMUtil;
633 typedef typename NMUtil::UnwrappedType<DecayedFunc>::type UnwrappedFunc;
634 UnwrappedFunc& unwrappedFunc = NMUtil::unwrap(decayedFunc);
635
636 d_funcManager_p(e_MOVE_CONSTRUCT, this, &unwrappedFunc);
637}
638
639// PRIVATE ACCESSORS
640inline
641std::size_t bslstl::Function_Rep::calcSooFuncSize() const BSLS_KEYWORD_NOEXCEPT
642{
643 std::size_t ret = 0;
644
645 if (d_funcManager_p) {
646 ret = d_funcManager_p(e_GET_SIZE,
647 const_cast<Function_Rep*>(this), 0);
648 }
649
650 return ret;
651}
652
653// CREATORS
654inline
655bslstl::Function_Rep::Function_Rep(const allocator_type& allocator)
657 : d_allocator(allocator)
658 , d_funcManager_p(0)
659 , d_invoker_p(0)
660{
661}
662
663// MANIPULATORS
664template <class FUNC>
668{
669 if (! invoker) {
670 // Leave this object in the empty state.
671 return; // RETURN
672 }
673
674 typedef typename Decay<FUNC>::type DecayedFunc;
675
676 // If 'FUNC' is wrapped in a 'bslalg::NothrowMovableWrapper', then the SOO
677 // size calculation works as though 'FUNC' were nothrow movable.
678 static const std::size_t k_SOO_FUNC_SIZE =
680 static const bool k_INPLACE = Soo::IsInplaceFunc<DecayedFunc>::value;
681
682 allocateBuf(k_SOO_FUNC_SIZE); // Might throw
683
684 // Target rep was successfully allocated, set 'd_funcManager_p'. If 'FUNC'
685 // is wrapped in a 'NothrowMovableWrapper', then unwrap it first, but use
686 // 'k_INPLACE' value for the original (potentially-wrapped) 'FUNC' so that
687 // the function manager knows whether to expect the object to be inplace or
688 // not.
689 typedef
691 UnwrappedFunc;
692 d_funcManager_p = &functionManager<UnwrappedFunc, k_INPLACE>;
693
694 // Copy or move the function argument into '*this' object. Note that this
695 // operation might throw.
696 constructTarget(BSLS_COMPILERFEATURES_FORWARD(FUNC, func));
697
698 // Exception danger has passed. Setting the invoker makes the
699 // 'Function_Rep' non-empty.
700 d_invoker_p = invoker;
701}
702
703template <class TP>
704inline
706{
707 if (! d_funcManager_p) {
708 return 0; // RETURN
709 }
710
711 const std::type_info& tpTypeInfo = typeid(TP);
712
713 void *ret = d_funcManager_p(e_GET_TARGET,
714 const_cast<Function_Rep *>(this),
715 const_cast<std::type_info*>(&tpTypeInfo));
716
717 // If 'TP' is a function (not pointer-to-function) type, 'ret' will be
718 // null, but we still must use a C-style cast to avoid the compiler error
719 // produced from converting a data pointer to a function pointer.
720 return (TP *) ret;
721}
722
723template <class TP, bool INPLACE>
724inline
726{
727 // If target fits in 'd_objbuf', then it is inplace; otherwise, its
728 // heap-allocated address is found in 'd_objbuf.d_object_p'. There is no
729 // need to dispatch using metaprogramming because the compiler will
730 // optimize away the compile-time conditional test.
731 return static_cast<TP*>(INPLACE ? &d_objbuf : d_objbuf.d_object_p);
732}
733
734// ACCESSORS
735inline
738{
739 return d_allocator;
740}
741
742inline
745{
746 return d_invoker_p;
747}
748
749inline
751{
752 return 0 == d_invoker_p;
753}
754
755
756
757#endif // ! defined(INCLUDED_BSLSTL_FUNCTION_REP)
758
759// ----------------------------------------------------------------------------
760// Copyright 2020 Bloomberg Finance L.P.
761//
762// Licensed under the Apache License, Version 2.0 (the "License");
763// you may not use this file except in compliance with the License.
764// You may obtain a copy of the License at
765//
766// http://www.apache.org/licenses/LICENSE-2.0
767//
768// Unless required by applicable law or agreed to in writing, software
769// distributed under the License is distributed on an "AS IS" BASIS,
770// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
771// See the License for the specific language governing permissions and
772// limitations under the License.
773// ----------------------------- END-OF-FILE ----------------------------------
774
775/** @} */
776/** @} */
777/** @} */
Definition bslma_bslallocator.h:580
Definition bslmf_decay.h:157
decay_imp< U, k_ISARRAY, k_ISFUNC >::type type
Definition bslmf_decay.h:166
Definition bslma_allocator.h:457
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:369
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:365
Definition bslstl_function_smallobjectoptimization.h:167
Definition bslstl_function_smallobjectoptimization.h:78
static const std::size_t k_NON_SOO_SMALL_SIZE
Definition bslstl_function_smallobjectoptimization.h:140
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLMF_MOVABLEREF_DEDUCE(...)
Definition bslmf_movableref.h:690
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used to supply memory for this object.
Definition bslstl_function_rep.h:737
void installFunc(BSLS_COMPILERFEATURES_FORWARD_REF(FUNC) func, GenericInvoker invoker)
Definition bslstl_function_rep.h:665
bool isEmpty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:750
TP * targetRaw() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:725
ManagerRet(std::size_t s)
Create a union holding the specified s size_t.
Definition bslstl_function_rep.h:486
GenericInvoker * invoker() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:744
TP * target() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_function_rep.h:705
Definition bslstl_algorithm.h:82
Definition bdldfp_decimal.h:5188
Definition bslalg_nothrowmovableutil.h:351
NothrowMovableUtil_Traits< TYPE >::UnwrappedType type
Definition bslalg_nothrowmovableutil.h:370
Namesapace for NothrowMovableWrapper traits and utilities.
Definition bslalg_nothrowmovableutil.h:344
Definition bslma_constructionutil.h:740
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1032
Definition bslstl_function_smallobjectoptimization.h:112
void * d_object_p
Definition bslstl_function_smallobjectoptimization.h:115