Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
function_ref.hpp File Reference

A non-owning reference to something callable. More...

#include <functional>
#include <memory>
#include <type_traits>
#include <utility>

Go to the source code of this file.

Classes

class  orrery::core::FunctionRef< Result(Args...)>
 A reference to a callable taking Args and returning Result. More...

Detailed Description

A non-owning reference to something callable.

The scheduler in backend/ has to hand a piece of work to a thread it did not compile against. The work is a lambda closing over whatever the caller happened to have to hand, the scheduler is a virtual interface chosen at run time, and a virtual function cannot be a template, so the closure has to be erased behind a uniform type at that boundary.

std::function is the usual answer and is the wrong one here. It owns what it holds, so constructing one from a closure that captures four spans may allocate, and the boundary it would sit on is crossed once per force evaluation: several times per timestep, for the whole length of a run. The ownership buys nothing, because the closure provably outlives the call. It is a local in the caller's frame and the callee returns before the caller does.

This is the type the standard adopted for the same reason, as std::function_ref in C++26. The project is on C++20, so it is written here rather than waited for, and it can be deleted when the compilers catch up.

The cost of not owning is the usual one, and it is real: a FunctionRef outliving the callable it refers to is a dangling pointer with no diagnostic. It is safe in the one shape this project uses it in, an argument to a call that returns before the full expression ends, and it should not be stored in a member or returned from a function.