1.. _module-pw_function: 2 3=========== 4pw_function 5=========== 6.. pigweed-module:: 7 :name: pw_function 8 9* **Familiar**. ``pw_function`` provides a standard, general-purpose API for 10 wrapping callable objects that's similar to `std::function`_. 11* **Optimized**. ``pw_function`` doesn't allocate (unless you want it to) and 12 uses several tricks to prevent code bloat. 13 14.. _std\:\:function: https://en.cppreference.com/w/cpp/utility/functional/function 15 16.. code-block:: c++ 17 18 #include "pw_function/function.h" 19 20 // pw::Function can be constructed from a function pointer... 21 int _a(int a, int b) { return a + b; } 22 pw::Function<int(int, int)> add(_a); 23 // ... or a lambda. 24 pw::Function<int(int)> square([](int num) { return num * num; }); 25 26 // pw::Callback can only be invoked once. After the first call, the target 27 // function is released and destroyed, along with any resources owned by 28 // that function. 29 pw::Callback<void(void)> flip_table_once([](void) { 30 // (╯°□°)╯︵ ┻━┻ 31 }); 32 33 add(5, 6); 34 add = nullptr; // pw::Function and pw::Callback are nullable 35 add(7, 2); // CRASH 36 37 square(4); 38 39 if (flip_table_once != nullptr) { // Safe to call 40 flip_table_once(); 41 } else { 42 // ┬─┬ノ( º _ ºノ) 43 } 44 45 46.. _module-pw_function-start: 47 48----------- 49Get started 50----------- 51.. tab-set:: 52 53 .. tab-item:: Bazel 54 55 Add ``@pigweed//pw_function`` to your target's ``deps``: 56 57 .. code-block:: 58 59 cc_library("...") { 60 # ... 61 deps = [ 62 # ... 63 "@pigweed//pw_function", 64 # ... 65 ] 66 } 67 68 This assumes that your Bazel ``WORKSPACE`` has a `repository 69 <https://bazel.build/concepts/build-ref#repositories>`_ named ``@pigweed`` 70 that points to the upstream Pigweed repository. 71 72 .. tab-item:: GN 73 74 Add ``$dir_pw_function`` to your target's ``deps``: 75 76 .. code-block:: 77 78 pw_executable("...") { 79 # ... 80 deps = [ 81 # ... 82 "$dir_pw_function", 83 # ... 84 ] 85 } 86 87 .. tab-item:: CMake 88 89 Link your library to ``pw_function``: 90 91 .. code-block:: 92 93 add_library(my_lib ...) 94 target_link_libraries(my_lib PUBLIC pw_function) 95 96Use ``pw_function`` in your C++ code: 97 98.. code-block:: c++ 99 100 #include "pw_function/function.h" 101 102 // ... 103 104.. _module-pw_function-guides: 105 106------ 107Guides 108------ 109 110Construct ``pw::Function`` from a function pointer 111================================================== 112:cpp:type:`pw::Function` is a move-only callable wrapper constructable from any 113callable object. It's templated on the signature of the callable it stores and 114implements the call operator; invoking a ``pw::Function`` object forwards to 115the stored callable. 116 117.. code-block:: c++ 118 119 int Add(int a, int b) { return a + b; } 120 121 // Construct a Function object from a function pointer. 122 pw::Function<int(int, int)> add_function(Add); 123 124 // Invoke the function object. 125 int result = add_function(3, 5); 126 EXPECT_EQ(result, 8); 127 128Construct ``pw::Function`` from a lambda 129======================================== 130.. code-block:: c++ 131 132 // Construct a function from a lambda. 133 pw::Function<int(int)> negate([](int value) { return -value; }); 134 EXPECT_EQ(negate(27), -27); 135 136Create single-use functions with ``pw::Callback`` 137================================================= 138:cpp:type:`pw::Callback` is a specialization of :cpp:type:`pw::Function` that 139can only be called once. After a :cpp:type:`pw::Callback` is called, the target 140function is released and destroyed, along with any resources owned by that 141function. A :cpp:type:`pw::Callback` in the "already called" state 142has the same state as a :cpp:type:`pw::Function` that has been assigned to 143nullptr. 144 145.. code-block:: cpp 146 147 pw::Callback<void(void)> flip_table_once([](void) { 148 // (╯°□°)╯︵ ┻━┻ 149 }); 150 151 flip_table_once(); // OK 152 flip_table_once(); // CRASH 153 154Nullifying functions and comparing to null 155========================================== 156``pw::Function`` and ``pw::Callback`` are nullable and can be compared to 157``nullptr``. Invoking a null function triggers a runtime assert. 158 159.. code-block:: c++ 160 161 // A function initialized without a callable is implicitly null. 162 pw::Function<void()> null_function; 163 164 // Null functions may also be explicitly created or set. 165 pw::Function<void()> explicit_null_function(nullptr); 166 167 pw::Function<void()> function([]() {}); // Valid (non-null) function. 168 function = nullptr; // Set to null, clearing the stored callable. 169 170 // Functions are comparable to nullptr. 171 if (function != nullptr) { 172 function(); 173 } 174 175``constexpr`` constructors and ``constinit`` expressions 176======================================================== 177The default constructor for :cpp:type:`pw::Function` is ``constexpr``, so 178default-constructed functions may be used in classes with ``constexpr`` 179constructors and in ``constinit`` expressions. 180 181.. code-block:: c++ 182 183 class MyClass { 184 public: 185 // Default construction of a pw::Function is constexpr. 186 constexpr MyClass() { ... } 187 188 pw::Function<void(int)> my_function; 189 }; 190 191 // pw::Function and classes that use it may be constant initialized. 192 constinit MyClass instance; 193 194``pw::Function`` as a function parameter 195======================================== 196When implementing an API which uses callbacks, ``pw::Function`` can be used in 197place of a function pointer or equivalent callable. 198 199.. code-block:: c++ 200 201 // Before: 202 void DoTheThing(int arg, void (*callback)(int result)); 203 204 // After: 205 void DoTheThing(int arg, const pw::Function<void(int result)>& callback); 206 // Note the parameter name within the function signature template for clarity. 207 208.. _module-pw_function-move-semantics: 209 210Move semantics 211============== 212:cpp:type:`pw::Function` is movable, but not copyable, so APIs must accept 213:cpp:type:`pw::Function` objects either by const reference (``const 214pw::Function<void()>&``) or rvalue reference (``const pw::Function<void()>&&``). 215If the :cpp:type:`pw::Function` simply needs to be called, it should be passed 216by const reference. If the :cpp:type:`pw::Function` needs to be stored, it 217should be passed as an rvalue reference and moved into a 218:cpp:type:`pw::Function` variable as appropriate. 219 220.. code-block:: c++ 221 222 // This function calls a pw::Function but doesn't store it, so it takes a 223 // const reference. 224 void CallTheCallback(const pw::Function<void(int)>& callback) { 225 callback(123); 226 } 227 228 // This function move-assigns a pw::Function to another variable, so it takes 229 // an rvalue reference. 230 void StoreTheCallback(pw::Function<void(int)>&& callback) { 231 stored_callback_ = std::move(callback); 232 } 233 234.. admonition:: Rules of thumb for passing a :cpp:type:`pw::Function` to a function 235 236 * **Pass by value**: Never. 237 This results in unnecessary :cpp:type:`pw::Function` instances and move 238 operations. 239 240 * **Pass by const reference** (``const pw::Function&``): When the 241 :cpp:type:`pw::Function` is only invoked. 242 243 When a :cpp:type:`pw::Function` is called or inspected, but not moved, take 244 a const reference to avoid copies and support temporaries. 245 246 * **Pass by rvalue reference** (``pw::Function&&``): When the 247 :cpp:type:`pw::Function` is moved. 248 249 When the function takes ownership of the :cpp:type:`pw::Function` object, 250 always use an rvalue reference (``pw::Function<void()>&&``) instead of a 251 mutable lvalue reference (``pw::Function<void()>&``). An rvalue reference 252 forces the caller to ``std::move`` when passing a preexisting 253 :cpp:type:`pw::Function` variable, which makes the transfer of ownership 254 explicit. It is possible to move-assign from an lvalue reference, but this 255 fails to make it obvious to the caller that the object is no longer valid. 256 257 * **Pass by non-const reference** (``pw::Function&``): Rarely, when modifying 258 a variable. 259 260 Non-const references are only necessary when modifying an existing 261 :cpp:type:`pw::Function` variable. Use an rvalue reference instead if the 262 :cpp:type:`pw::Function` is moved into another variable. 263 264Calling functions that use ``pw::Function`` 265=========================================== 266A :cpp:type:`pw::Function` can be implicitly constructed from any callback 267object. When calling an API that takes a :cpp:type:`pw::Function`, simply pass 268the callable object. There is no need to create an intermediate 269:cpp:type:`pw::Function` object. 270 271.. code-block:: c++ 272 273 // Implicitly creates a pw::Function from a capturing lambda and calls it. 274 CallTheCallback([this](int result) { result_ = result; }); 275 276 // Implicitly creates a pw::Function from a capturing lambda and stores it. 277 StoreTheCallback([this](int result) { result_ = result; }); 278 279When working with an existing :cpp:type:`pw::Function` variable, the variable 280can be passed directly to functions that take a const reference. If the function 281takes ownership of the :cpp:type:`pw::Function`, move the 282:cpp:type:`pw::Function` variable at the call site. 283 284.. code-block:: c++ 285 286 // Accepts the pw::Function by const reference. 287 CallTheCallback(my_function_); 288 289 // Takes ownership of the pw::Function. 290 void StoreTheCallback(std::move(my_function)); 291 292Managing inline storage size 293============================ 294By default, ``pw::Function`` stores its callable inline within the object. The 295inline storage size defaults to the size of one pointer, but is configurable 296through the build system. 297 298:cpp:type:`pw::InlineFunction` is similar to ``pw::Function``, 299but is always inlined. That is, even if dynamic allocation is enabled for 300``pw::Function``, ``pw::InlineFunction`` will fail to compile if 301the callable is larger than the inline storage size. 302 303Attempting to construct a function from a callable larger than its inline size 304is a compile-time error unless dynamic allocation is enabled. 305 306.. admonition:: Inline storage size 307 308 The default inline size of one pointer is sufficient to store most common 309 callable objects, including function pointers, simple non-capturing and 310 capturing lambdas, and lightweight custom classes. 311 312.. code-block:: c++ 313 314 // The lambda is moved into the function's internal storage. 315 pw::Function<int(int, int)> subtract([](int a, int b) { return a - b; }); 316 317 // Functions can be also be constructed from custom classes that implement 318 // operator(). This particular object is large (8 ints of space). 319 class MyCallable { 320 public: 321 int operator()(int value); 322 323 private: 324 int data_[8]; 325 }; 326 327 // Compiler error: sizeof(MyCallable) exceeds function's inline storage size. 328 pw::Function<int(int)> function((MyCallable())); 329 330.. _module-pw_function-dynamic-allocation: 331 332Dynamic allocation 333================== 334You can configure the inline allocation size of ``pw::Function`` and whether it 335dynamically allocates, but it applies to all uses of ``pw::Function``. 336 337As mentioned in :ref:`module-pw_function-design`, ``pw::Function`` is an alias 338of Fuchsia's ``fit::function``. ``fit::function`` allows you to specify the 339inline (static) allocation size and whether to dynamically allocate if the 340callable target doesn't inline. If you want to use a function class with 341different attributes, you can interact with ``fit::function`` directly but note 342that the resulting functions may not be interchangeable, i.e. callables for one 343might not fit in the other. 344 345When ``PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION`` is enabled, a ``pw::Function`` 346will use dynamic allocation to store callables that exceed the inline size. 347An :ref:`allocator <module-pw_allocator>` type can be optionally supplied as a 348template argument. The default allocator type can also be changed by overriding 349``PW_FUNCTION_DEFAULT_ALLOCATOR_TYPE`` (the ``value_type`` of the allocator 350is irrelevant, since it must support rebinding). When dynamic allocation is 351enabled but a compile-time check for the inlining is still required, 352``pw::InlineFunction`` can be used. 353 354.. warning:: 355 356 If ``PW_FUNCTION_ENABLE_DYNAMIC_ALLOCATION`` is enabled then attempts to 357 cast from :cpp:type:`pw::InlineFunction` to a regular 358 :cpp:type:`pw::Function` will **ALWAYS** allocate memory. 359 360.. note:: 361 362 When building Pigweed itself for host platforms, we enable dynamic 363 allocation. This is required for some modules that use ``pw::Function``, 364 like :ref:`module-pw_bluetooth_sapphire`. But it is *not* the default for 365 downstream projects because it introduces a difference between host and 366 non-host builds. This difference has the potential to cause breakages if 367 code is built for host first, and then later ported to device. 368 369Invoking ``pw::Function`` from a C-style API 370============================================ 371.. _trampoline layers: https://en.wikipedia.org/wiki/Trampoline_(computing) 372 373One use case for invoking ``pw_function`` from a C-style API is to automate the 374generation of `trampoline layers`_. See 375:cpp:type:`pw::function::GetFunctionPointer()`. 376 377.. _module-pw_function-reference: 378 379------------- 380API reference 381------------- 382 383``pw::Function`` 384================ 385.. doxygentypedef:: pw::Function 386 387``pw::InlineFunction`` 388====================== 389.. doxygentypedef:: pw::InlineFunction 390 391``pw::Callback`` 392================ 393.. doxygentypedef:: pw::Callback 394 395``pw::InlineCallback`` 396====================== 397.. doxygentypedef:: pw::InlineCallback 398 399``pw::bind_member()`` 400===================== 401.. doxygenfunction:: pw::bind_member 402 403``pw::function::GetFunctionPointer()`` 404====================================== 405.. doxygenfile:: pw_function/pointer.h 406 :sections: detaileddescription 407.. doxygenfunction:: GetFunctionPointer() 408.. doxygenfunction:: GetFunctionPointer(const FunctionType&) 409 410``pw::function::GetFunctionPointerContextFirst()`` 411================================================== 412.. doxygenfunction:: GetFunctionPointerContextFirst() 413.. doxygenfunction:: GetFunctionPointerContextFirst(const FunctionType&) 414 415``pw::ScopeGuard`` 416================== 417.. doxygenclass:: pw::ScopeGuard 418 :members: 419 420.. _module-pw_function-design: 421 422------ 423Design 424------ 425``pw::Function`` is an alias of Fuchsia's ``fit::function_impl`` and 426``pw::Callback`` is an alias of Fuchsia's ``fit::callback_impl``. See the 427following links for more information about Fuchsia's implementations: 428 429* `//third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h <https://cs.opensource.google/pigweed/pigweed/+/main:third_party/fuchsia/repo/sdk/lib/fit/include/lib/fit/function.h>`_ 430* `fit::function <https://fuchsia.googlesource.com/fuchsia/+/HEAD/sdk/lib/fit/#fit_function>`_ 431 432.. _module-pw_function-non-literal: 433 434Why ``pw::Function`` is not a literal 435===================================== 436The default constructor for ``pw::Function`` is ``constexpr`` but 437``pw::Function`` is not a literal type. Instances can be declared ``constinit`` 438but can't be used in ``constexpr`` contexts. There are a few reasons for this: 439 440* ``pw::Function`` supports wrapping any callable type, and the wrapped type 441 might not be a literal type. 442* ``pw::Function`` stores inline callables in a bytes array, which is not 443 ``constexpr``-friendly. 444* ``pw::Function`` optionally uses dynamic allocation, which doesn't work in 445 ``constexpr`` contexts (at least before C++20). 446 447------------ 448Size reports 449------------ 450 451Comparing ``pw::Function`` to a traditional function pointer 452============================================================ 453The following size report compares an API using a :cpp:type:`pw::Function` to a 454traditional function pointer. 455 456.. include:: function_size 457 458Typical sizes of various callable types 459======================================= 460The table below demonstrates typical sizes of various callable types, which can 461be used as a reference when sizing external buffers for ``pw::Function`` 462objects. 463 464.. include:: callable_size 465