Lumiera  0.pre.03
»edit your freedom«
LazyInit_test Class Reference

Description

Test:
Verify a mix-in to allow for lazy initialisation of complex infrastructure tied to a std::function; the intention is to have a »trap« hidden in the function itself to trigger on first use and perform the one-time initialisation, then finally lock the object at a fixed place.
See also
lazy-init.hpp
lib::RandomDraw

Definition at line 59 of file lazy-init-test.cpp.

Classes

struct  LazyDemo
 elaborate setup used for integration test More...
 

Private Member Functions

void run (Arg)
 
void verify_complexUsageWithCopy ()
 
void verify_inlineStorage ()
 
void verify_lazyInitialisation ()
 
void verify_TargetRelocation ()
 
void verify_triggerMechanism ()
 
void verify_trojanLambda ()
 

Member Function Documentation

◆ verify_trojanLambda()

void verify_trojanLambda ( )
inlineprivate
Test:
verify construction of the »trap« front-end eventually to trigger initialisation
  • this test does not involve any std::function, rather a heap-allocated copy of a λ
Remarks
the purpose of this convoluted scheme is for the delegate to perform initialisation, taking into account the current memory location „sniffed“ by the trojan.

Definition at line 86 of file lazy-init-test.cpp.

◆ verify_inlineStorage()

void verify_inlineStorage ( )
inlineprivate
Test:
verify that std::function indeed stores a simple functor inline.
Remarks
The implementation of LazyInit relies crucially on a known optimisation in the standard library ─ which unfortunately is not guaranteed by the standard: Typically, std::function will apply small object optimisation to place a very small functor directly into the wrapper, if the payload has a trivial copy-ctor. Libstdc++ is known to be rather restrictive, while other implementations trade increased storage size of std::function against more optimisation possibilities. LazyInit exploits this optimisation to „spy“ about the current object location, allowing to execute the lazy initialisation on first use, without further help by client code. This trickery seems to be the only way, since λ-capture by reference is broken after copying or moving the host object (typically required for DSL use). In case this turns out to be fragile, LazyInit should become a "LateInit" and needs help by the client or the user to trigger initialisation; alternatively the DSL could be split off into a separate builder object distinct from RandomDraw.

Definition at line 159 of file lazy-init-test.cpp.

◆ verify_TargetRelocation()

void verify_TargetRelocation ( )
inlineprivate
Test:
verify navigating an object structure by applying known offsets consecutively from a starting point within an remote instance
Remarks
in the real usage scenario, we know only the offset and attempt to find home without knowing the layout.

Definition at line 192 of file lazy-init-test.cpp.

◆ verify_triggerMechanism()

void verify_triggerMechanism ( )
inlineprivate
Test:
demonstrate the trigger mechanism in isolation

Definition at line 239 of file lazy-init-test.cpp.

References lib::anonymous_namespace{lazy-init.hpp}::FUNCTOR_PAYLOAD_OFFSET.

◆ verify_lazyInitialisation()

void verify_lazyInitialisation ( )
inlineprivate
Test:
demonstrate a basic usage scenario

Definition at line 288 of file lazy-init-test.cpp.

◆ verify_complexUsageWithCopy()

void verify_complexUsageWithCopy ( )
inlineprivate
Test:
use an elaborately constructed example to cover more corner cases
  • the function to manage and initialise lazily is a member of the derived class
  • the initialisation routine adapts this function and links it with the current object location; thus, invoking this function on a copy would crash / corrupt memory.
  • however, as long as initialisation has not been triggered, LazyDemo instances can be copied; they may even be assigned to existing instances, overwriting their state.
  • a second given function will be chained behind the first one; this happens immediately if the first function was already invoked (and this initialised)
  • but when however both functions are attached immediately, prior to invocation, then an elaborate chain of initialisers is setup behind the scenes and played back in definition order once lazy initialisation is triggered
  • all the intermediary state is safe to copy and move and fork
    Remarks
    11/2023 memory allocations were verified using lib::test::Tracker and the EventLog

Definition at line 393 of file lazy-init-test.cpp.

References VERIFY_ERROR.

+ Inheritance diagram for LazyInit_test:
+ Collaboration diagram for LazyInit_test:

The documentation for this class was generated from the following file: