BLI: add high level documentation for core data structures #25

Merged
Jacques Lucke merged 14 commits from JacquesLucke/blender-developer-docs:core-data-structures into main 2024-02-19 19:09:34 +01:00
Showing only changes of commit a9e41558a4 - Show all commits

View File

@ -1 +1,47 @@
# Functions # 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
```