BLI: add high level documentation for core data structures #25
@ -1 +1,47 @@
|
||||
# Functions
|
||||
|
||||
There are many ways to store a reference to a function. This document gives an overview over those and gives recommendations for when to use which approach.
|
||||
|
||||
1. Pass function pointer and user data (as void *) separately:
|
||||
- The only method that is compatible with C interfaces.
|
||||
- Is cumbersome to work with in many cases, because one has to keep track of two parameters.
|
||||
- Not type safe at all, because of the void pointer.
|
||||
- It requires workarounds when one wants to pass a lambda into a function.
|
||||
2. Using `std::function`:
|
||||
- It works well with most callables and is easy to use.
|
||||
- Owns the callable, so it can be returned from a function more safely than other methods.
|
||||
- Requires that the callable is copyable.
|
||||
- Requires an allocation when the callable is too large (typically > 16 bytes).
|
||||
3. Using a template for the callable type:
|
||||
- Most efficient solution at runtime, because compiler knows the exact callable at the place
|
||||
where it is called.
|
||||
- Works well with all callables.
|
||||
- Requires the function to be in a header file.
|
||||
- It's difficult to constrain the signature of the function.
|
||||
4. Using `blender::FunctionRef` ([source](https://projects.blender.org/blender/blender/src/branch/main/source/blender/blenlib/BLI_function_ref.hh)):
|
||||
- Second most efficient solution at runtime.
|
||||
- It's easy to constrain the signature of the callable.
|
||||
- Does not require the function to be in a header file.
|
||||
- Works well with all callables.
|
||||
- It's a non-owning reference, so it *cannot* be stored safely in general.
|
||||
|
||||
The following diagram helps to decide which approach to use when building an API where the user has to pass in a function.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
is_called_from_c["Is called from C code?"]
|
||||
is_stored_when_function_ends["Is stored when function ends?"]
|
||||
is_call_performance_bottleneck["Call is performance bottleneck?"]
|
||||
use_function_pointer["Use function pointer and user data (approach 1)."]
|
||||
use_std_function["Use `std::function` (approach 2)."]
|
||||
use_template["Use `template<typename Fn>` (approach 3)."]
|
||||
use_function_ref["Use `blender::FunctionRef` (approach 4)."]
|
||||
|
||||
|
||||
is_called_from_c --"yes"--> use_function_pointer
|
||||
is_called_from_c --"no"--> is_stored_when_function_ends
|
||||
is_stored_when_function_ends --"yes"--> use_std_function
|
||||
is_stored_when_function_ends --"no"--> is_call_performance_bottleneck
|
||||
is_call_performance_bottleneck --"no"--> use_function_ref
|
||||
is_call_performance_bottleneck --"yes"--> use_template
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user