67#ifndef LIB_LAZY_INIT_H
68#define LIB_LAZY_INIT_H
102 char* anchorAddr =
reinterpret_cast<char*
> (unConst(anchor));
103 char* subjectAddr =
reinterpret_cast<char*
> (unConst(subject));
104 return subjectAddr - anchorAddr;
111 char* anchorAddr =
reinterpret_cast<char*
> (unConst(anchor));
112 char* adjusted = anchorAddr + offset;
113 void* rawTarget =
reinterpret_cast<void*
> (adjusted);
114 return static_cast<TAR*
> (rawTarget);
129 std::function<
RawAddr(
void)> probe = [slot]{
return RawAddr(&slot); };
133 throw err::Fatal{
"Unable to use lib::LazyInit because std::function does not "
134 "apply small-object optimisation with inline storage."};
151 template<
class DEL,
typename RET,
typename... ARGS>
156 (ARGS ...args) -> RET
158 auto currLocation = &delegate;
159 auto& functor = (*delegate) (currLocation);
161 return functor (forward<ARGS> (args)...);
181 static_assert (
_Fun<DEL>(),
"Delegate must be function-like");
183 static_assert (
_Fun<Ret>(),
"Result from invoking delegate must also be function-like");
184 static_assert (
has_Sig<Ret, SIG>(),
"Result from delegate must expose target signature");
205 template<
class PAR =EmptyBase>
224 throw err::State{
"Component was already configured with a processing function, "
225 "which binds into a fixed object location. It can not be moved anymore."
226 , err::LUMIERA_ERROR_LIFECYCLE};
234 throw err::State{
"Component was already configured with a processing function, "
235 "which binds into a fixed object location. It can not be moved anymore."
236 , err::LUMIERA_ERROR_LIFECYCLE};
246 template<
typename...ARGS>
248 : PAR(forward<ARGS> (parentCtorArgs)...)
255 template<
class SIG,
class INI,
typename...ARGS>
256 LazyInit (std::function<SIG>& targetFunctor, INI&& initialiser, ARGS&& ...parentCtorArgs)
257 : PAR(forward<ARGS> (parentCtorArgs)...)
279 PAR::operator= (ref);
290 PAR::operator= (move (rref));
310 template<
class SIG,
class INI>
323 using TargetFun = std::function<SIG>;
327 return disabledFunctor;
331 template<
class SIG,
class INI>
335 if (
isInit() and targetFunctor)
337 using ExpectedArg = _FunArg<INI>;
338 initialiser (
static_cast<ExpectedArg
> (
this));
347 return storageHandle;
351 static DelegateType<SIG>*
358 static std::function<SIG>
362 return std::function<SIG>();
363 auto* pendingDelegate = getPointerToDelegate<SIG>(*pendingInit);
364 return (*pendingDelegate) (location);
367 template<
class SIG,
class INI>
371 using TargetFun = std::function<SIG>;
372 using ExpectedArg = _FunArg<INI>;
374 [performInit = forward<INI> (initialiser)
376 ,targetOffset = captureRawAddrOffset (
this, &targetFunctor)]
377 (
RawAddr location) -> TargetFun&
379 TargetFun* target = relocate<TargetFun> (location, -FUNCTOR_PAYLOAD_OFFSET);
380 LazyInit* self = relocate<LazyInit> (target, -targetOffset);
385 (*target) = maybeInvoke<SIG> (previousInit, location);
387 performInit (
static_cast<ExpectedArg
> (self));
Buffer to place and maintain an object instance privately within another object.
Mix-in for lazy/delayed initialisation of an embedded functor.
LazyInit & operator=(LazyInit const &ref)
DelegateType< SIG > emptyInitialiser()
static DelegateType< SIG > * getPointerToDelegate(HeapStorage &buffer)
std::shared_ptr< HeapStorage > PendingInit
PendingInit && __trapLocked(PendingInit &&init)
DelegateType< void(void)> PlaceholderType
void installInitialiser(std::function< SIG > &targetFunctor, INI &&initialiser)
PendingInit const & __trapLocked(PendingInit const &init)
DelegateType< SIG > buildInitialiserDelegate(std::function< SIG > &targetFunctor, INI &&initialiser)
static std::function< SIG > maybeInvoke(PendingInit const &pendingInit, RawAddr location)
std::function< std::function< SIG > &(RawAddr)> DelegateType
PendingInit prepareInitialiser(std::function< SIG > &targetFunctor, INI &&initialiser)
LazyInit(std::function< SIG > &targetFunctor, INI &&initialiser, ARGS &&...parentCtorArgs)
prepare an initialiser to be activated on first use
LazyInit(MarkDisabled, ARGS &&...parentCtorArgs)
InPlaceBuffer< PlaceholderType > HeapStorage
LazyInit(LazyInit const &ref)
void installEmptyInitialiser()
PendingInit pendingInit_
manage heap storage for a pending initialisation closure
LazyInit(LazyInit &&rref)
»Trojan Function« builder.
static auto generateTrap(DEL *delegate)
Invocation: build a Lambda to activate the »Trap« and then to forward the invocation to the actual fu...
static auto buildTrapActivator(DEL *delegate, _Fun< RET(ARGS...)>)
Derived specific exceptions within Lumiera's exception hierarchy.
Lumiera error handling (C interface).
Metaprogramming tools for detecting and transforming function types.
ptrdiff_t captureRawAddrOffset(RawAddr anchor, RawAddr subject)
const ptrdiff_t FUNCTOR_PAYLOAD_OFFSET
static TAR * relocate(RawAddr anchor, ptrdiff_t offset)
Implementation namespace for support and library code.
LumieraError< LERR_(STATE)> State
bool isCloseBy(A &&a, B &&b, size_t consideredNearby=50)
determine heuristically if two objects are located „close to each other“ in memory.
bool isSameObject(A const &a, B const &b)
compare plain object identity, based directly on the referee's memory identities.
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Helper allowing type erasure while holding the actual object inline.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...