mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-16 00:46:03 +08:00
* Add ranges * Initial Hugo setup * Work in progress * Added selection for local or remote site * Updated to 'light' theme * Changed to using Hextra Hugo theme * Changed to using Hextra Hugo theme * Changed to Hextra Hugo theme * Change to Hextra Hugo theme * Updated Hugo setup. * Updated Hugo setup. # Conflicts: # docs/releases/_index.md * Work in progress * Added new fonts Added new documentation * Latest documentation updates * Latest documentation updates # Conflicts: # docs/containers/array.md # docs/containers/array_view.md # docs/containers/array_wrapper.md # docs/containers/bip_buffer_spsc_atomic.md # docs/containers/bitset.md # docs/containers/indirect_vector.md # docs/containers/vector.md # docs/getting-started/compilers.md * Added bloom_filter markdown doc * Added more documentation Updated CSS for light and dark modes * Fixed some menus Added mode documentation files * Updated CSS rules Added badges to home page Added uniqur_ptr + pool tutorial * Fixed formatting on the home page markdown Modified light amd dark code formatting * Updated unique_ptr-with-pool * Added container and shared message tutorials * Updates to documentation * Added const_multimap * Updated source-formatting.md * Added initial raw text files form Web site editor * Innore coverage build directory * Exported raw text documentation files from the web site editor * Hugo updates * Added Hugo intalation and markdown descriptions * More addition to the documentation * Added closure.md and updates to delegate.md * Added format.md * Added documentation for etl::delegate_observable, etl::function, Base64 codec * Added io_port documentation * Added basic_format_spec * Added documentation for string_stream and string utilities. * Added more documentation Updated the documentation CSS * Added documentation for clocks, day, duration * Added more documentation for chrono classes Updated callouts * More chrono documentation * Completed chrono documentation * Maths functions documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Completed maths documentation * Added multiple documentation files * Added iterator.md * Added debug_count.md and versions.md * Added debug_count.md and versions.md * Added more documentation * More documentation * Added some design pattern documentation Modified some of the layout files Modified the About documentation * Converted more documentation pages Modified the site CSS * Added more documentation Moced some documentation files to new directories * Added more documentation Tweaks to CSS * Added callback_timer_deferred_locked documentation * Added callback_timer_locked documentation * More documentation updates * More documentation updates * More documentation updates * New documentation files. Harmonised file name format * New documentation files. * Multiple document updates * Multiple document updates * Final conversion of web pages * Updates before PR * Updates before PR * Updates before PR # Conflicts: # docs/blog/_index.md * Final pre PR updates * Updates to message framework documentation * Renamed directory * Fix spelling * Added author and date to blog files Moved documentation files merged from development * Fixed 'Description' typo * Fix typos # Conflicts: # docs/IO/io_port.md # docs/containers/sets/const-multiset.md # docs/containers/sets/const-set.md # docs/maths/correlation.md # docs/maths/gamma.md * Renamed two files to lower case * Minor renaming * Added author and date * Updated callout on bresenham_line.md Added support for showing the ETL version on the documentation first page, by copying the version.txt file as a hugo asset. Updated the Python 'update_release.py' to copy 'version.txt' * Replace space in filename with hyphen. Added more information to hugo-commands.md * Replace space in filename with hyphen. Added more information to hugo-commands.md # Conflicts: # docs/getting-started/view-the-docs-locally/hugo-commands.md * Added a link to pseudo_moving_average.md * Updated title pages for groups * Fixed missing 404 for non-existent pages * Fixed coordinate variable names in the 'Calculating the intersection' example --------- Co-authored-by: Roland Reichwein <Roland.Reichwein@bmw.de> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com> Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.co.uk>
221 lines
9.6 KiB
Markdown
221 lines
9.6 KiB
Markdown
---
|
||
title: "delegate vs inplace_function"
|
||
weight: 1
|
||
---
|
||
|
||
## Efficiency and performance
|
||
### Invocation cost
|
||
|
||
**delegate**
|
||
One indirect call via stub function pointer; no allocation; forwards args directly; minimal overhead.
|
||
|
||
**inplace_function**
|
||
One indirect call via vtable invoke pointer; no allocation; overhead effectively the same as `delegate`.
|
||
|
||
### Copy / move cost
|
||
|
||
**delegate**
|
||
Trivial copy/move (object pointer + stub pointer).
|
||
|
||
**inplace_function**
|
||
Copies/moves the stored callable in an inline buffer; cost depends on callable traits; may run destructor on clear/reset.
|
||
|
||
### Size / footprint
|
||
|
||
**delegate**
|
||
Typically two pointers; very small, stable footprint.
|
||
|
||
**inplace_function**
|
||
Buffer + vtable pointer + object pointer; size depends on `Object_Size`/`Object_Alignment`.
|
||
|
||
### Ownership / lifetime
|
||
|
||
**delegate**
|
||
Non-owning for functors/lambdas; stores pointer to external callable; caller must ensure lifetime.
|
||
|
||
**inplace_function**
|
||
Owning; stores a copy/move of the callable inline (RAII).
|
||
|
||
### When to prefer
|
||
|
||
**delegate**
|
||
Minimal footprint, cheapest copies, free/member function binding, controlled lifetimes.
|
||
|
||
**inplace_function**
|
||
Value semantics, safe storage of lambdas with captures, uniform SBO wrapper.
|
||
|
||
## External API differences
|
||
|
||
### Template shape and size
|
||
|
||
`delegate<TSignature>`
|
||
`inplace_function<TSignature, Object_Size = 32, Object_Alignment = alignof(void*)>`
|
||
|
||
### Construction / binding
|
||
|
||
**delegate**
|
||
`create<FreeFn>()`
|
||
`create(T& obj, Method)` and `create(const T& obj, ConstMethod)` at run time
|
||
`create<T, Method, Instance>()`
|
||
Construct from functor/lambda by reference (non-owning); rvalues deleted to avoid dangling
|
||
`set()` mirrors `create()` for re-binding
|
||
|
||
**inplace_function**
|
||
Constructor from function pointer
|
||
Constructor from object + (const/non-const) member function (run time)
|
||
Constructor from functor/lambda by (const) reference; callable stored inline (owning)
|
||
`set()` mirrors constructors; also `set<FreeFn>()` and `set<T, Method, Instance>()` (compile time)
|
||
`create<FreeFn>()`, `create<T, Method, Instance>()` (compile time)
|
||
`make_inplace_function` helpers: `make_inplace_function(free_fn)`, `make_inplace_function(obj, &T::Method)` , `make_inplace_function<TSignature>(lambda)`.
|
||
|
||
### Equality and swap
|
||
|
||
**delegate**
|
||
`operator==`/`!=` compare stub and object; structural equality.
|
||
|
||
**inplace_function**
|
||
`operator==`/`!=` with `nullptr`; `swap()` provided; no general equality between two functions.
|
||
|
||
### Introspection helpers
|
||
**delegate**
|
||
`delegate_tag`
|
||
`is_delegate<T>`.
|
||
|
||
**inplace_function**
|
||
`is_inplace_function<T>`.
|
||
|
||
### Call helpers
|
||
`is_valid()`
|
||
`explicit bool`
|
||
`call_if(...)`
|
||
`call_or(alternative, ...)`
|
||
`call_or<FreeFn>(...)`.
|
||
|
||
### Functor storage semantics
|
||
**delegate**
|
||
Non-owning pointer to external functor/lambda.
|
||
|
||
**inplace_function**
|
||
Owns a copy/move in fixed buffer.
|
||
|
||
### Size control
|
||
**delegate**
|
||
Fixed small size (two pointers).
|
||
|
||
**inplace_function**
|
||
User-controlled via `Object_Size`/`Object_Alignment`; aliases `inplace_function_for` and `inplace_function_for_any` to compute required size/alignment.
|
||
|
||
### C++ language features
|
||
Classic non-type template parameter APIs; C++17 "auto" `make_*` helpers exist when enabled.
|
||
|
||
## Performance differences:
|
||
|
||
### Call overhead
|
||
**delegate**
|
||
One indirect call through a stub function pointer; minimal overhead.
|
||
|
||
**inplace_function**
|
||
One indirect call via `vtable->invoke(object, ...);` typically one extra pointer load; practically similar.
|
||
|
||
### Copy / move and lifetime
|
||
**delegate**
|
||
Trivial POD-like copy/move (object pointer + stub); no construction/destruction of target.
|
||
|
||
**inplace_function**
|
||
Copies/moves/destroys the stored callable in the inline buffer; cost depends on callable traits.
|
||
|
||
### Construction / binding cost
|
||
**delegate**
|
||
Binding free/member functions sets two pointers; binding a functor stores its address (non-owning).
|
||
|
||
**inplace_function**
|
||
Constructs a copy/move of the callable into the SBO buffer; more work up front.
|
||
|
||
### Memory footprint and cache locality
|
||
**delegate**
|
||
~2 pointers regardless of target; high container density and good cache locality.
|
||
|
||
**inplace_function**
|
||
Buffer + vtable pointer + object pointer; larger, size depends on Object_Size/Object_Alignment.
|
||
|
||
### Clear / reset cost
|
||
**delegate**
|
||
Clears pointers; no destructor invocation.
|
||
|
||
**inplace_function**
|
||
May run callable’s destructor; potentially non-trivial.
|
||
|
||
### Determinism / Real-time suitability
|
||
**delegate**
|
||
Very predictable and minimal costs at call/copy/reset; good for ISR/RT paths.
|
||
|
||
**inplace_function**
|
||
Deterministic at call; copy/move/reset depend on callable’s traits (still allocation-free).
|
||
|
||
## Rule of thumb
|
||
- Use `delegate` when:
|
||
You only bind free/member functions or non-owning functors and want the smallest handle with the cheapest copies.
|
||
|
||
- Use `inplace_function` when:
|
||
You must own captured state safely (value semantics) and still avoid the heap; accept slightly larger handle/copy costs for safety.
|
||
|
||
## Choose etl::delegate when
|
||
- You need the smallest possible callable handle (two pointers) for large arrays/vectors of callbacks.
|
||
- You must avoid any allocation, construction, destruction, or SBO buffer management in the callable wrapper.
|
||
- You bind free functions or member functions and the target object’s lifetime is externally guaranteed.
|
||
- You want trivial copy/move/equality semantics (copy two pointers; compare stub+object) for fast shuffling/lookup.
|
||
- You need deterministic, RT/ISR-safe behavior with no hidden destructors or move/destruct paths on clear/reset.
|
||
- You build static/ROM lookup tables of callbacks (compile-time create<Fn>(), create<T,Method,Instance>()).
|
||
- You store callbacks in fixed-capacity containers (etl::array/vector) and must minimize memory per element.
|
||
- You need ABI-stable, non-owning callback tokens passed across modules without copying callables.
|
||
- You already use etl::delegate_service or similar indexed dispatch; its API expects etl::delegate.
|
||
- You don't want to size/tune an inline buffer (Object_Size/Object_Alignment) per signature or platform.
|
||
|
||
### Typical scenarios
|
||
- Interrupt vectors, GPIO/event ISR callbacks, hard real-time control loops.
|
||
- Command/ID -> handler tables, message routing switchboards, state-machine transition actions.
|
||
- Global registries/singletons where handler objects are static or live for program lifetime.
|
||
- Shared tables of callbacks across DLLs/modules where owning captured state is undesirable.
|
||
|
||
### Why etl::delegate over etl::inplace_function in these cases
|
||
- Lower footprint: always two pointers versus user-sized SBO buffer + vtable pointer + object pointer.
|
||
- Lower copy/move cost: trivial POD-like copies; no callable copy/move/dtor required.
|
||
- Non-owning by design: avoids accidental copies of heavy callables; no lifetime surprises at clear/reset.
|
||
- Compile-time binding support: completely payload-free delegates for fixed targets (no storage touched).
|
||
- Equality: pointer-based equality lets you deduplicate/lookup handlers efficiently.
|
||
|
||
### Notes
|
||
- `etl::delegate` is non-owning; only choose it when the bound object outlives the delegate (rvalue lambdas are rejected by API).
|
||
- Prefer `etl::inplace_function`0 when you must own captured state (value semantics) or need to accept arbitrary lambdas safely.
|
||
|
||
## Choose etl::inplace_function when
|
||
- You need value semantics (own the callable) so lifetimes are safe without tracking external objects.
|
||
- You want to accept arbitrary lambdas with captures and store them inline using small-buffer optimization (no heap).
|
||
- You need a single uniform callable wrapper that erases the concrete type across modules/APIs.
|
||
- You plan to copy/move callbacks between threads/queues safely (callable is self-contained in the buffer).
|
||
- You must avoid dynamic allocation but still need to store captured state (tune Object_Size/Object_Alignment).
|
||
- You want compile-time or run-time binding to free functions, member functions, and functors in one type.
|
||
- You need reset/clear semantics that correctly destroy the stored callable (RAII).
|
||
- You prefer exceptions on misuse (invoking uninitialized) to surface bugs early.
|
||
|
||
### Typical scenarios
|
||
- Job systems, task queues, and executors that capture small state per task without heap churn.
|
||
- Pipelines and event buses that accept user-provided lambdas with captures.
|
||
- Configurable command tables where handlers carry lightweight configuration/state.
|
||
- Deferred work items, timeouts, and continuations stored in fixed-capacity containers.
|
||
- API boundaries returning/storing callbacks where the provider shouldn't manage the callee's lifetime.
|
||
|
||
### Why etl::inplace_function over etl::delegate in these cases
|
||
- Ownership: inplace_function owns the callable; no external lifetime management needed.
|
||
- Safety with captures: stores copies/moves of lambdas/functors; no dangling pointers to external objects.
|
||
- Uniform wrapper: a single type covers free/member/functor targets with the same call site and storage.
|
||
- No heap: SBO avoids allocations while still allowing captured state; predictable embedded-friendly footprint.
|
||
- Destruction: clear()/reset() run the callable's destructor when needed; no leaks or latent state.
|
||
|
||
### Notes
|
||
- Tune the buffer size/alignment to the largest expected callable; too-small buffers will `static_assert`.
|
||
- Copy/move cost depends on the callable; prefer lightweight captures for best performance.
|
||
- Invocation overhead is one indirect call through a vtable stub (similar to delegate).
|
||
- Use make_inplace_function helpers or create<> to bind targets; is_valid(), call_if(), and call_or() are available.
|
||
- If you only bind free/member functions and can guarantee lifetimes, etl::delegate is smaller and cheaper to copy.
|