SERiF v0.0.1a
Stellar Evolution and Rotation in Four Dimensions
Loading...
Searching...
No Matches
serif::utils::dependencies Namespace Reference

Namespaces

namespace  detail
 
namespace  keys
 

Classes

struct  AllNodesObserver
 One registration can inspect every result without building a graph-sized observer tuple. More...
 
struct  Binding
 
struct  Bindings
 
struct  BoundType
 
class  Computation
 
class  ComputationCache
 Execute a computational graph on demand, publishing immutable results only after the entire request succeeds. More...
 
class  ComputationGraph
 
class  DependencyContext
 
class  DependencyContextView
 
class  DependencyContextView< ParentT, KeyList< KeyTs... > >
 
struct  EdgeObserver
 
class  GraphTiming
 Collect independent graph bindings without mixing timers into numerical restart history. More...
 
struct  GraphTimingFactory
 Bind one generic timing observer after the model's complete graph type is known. More...
 
struct  GraphTimingRun
 One graph binding's declaration-ordered catalog, including nodes which never execute. More...
 
struct  HasBinding
 
struct  KeyList
 An ordered collection of role keys, independent of their associated value types. More...
 
struct  KeyListBindings
 
struct  KeyListBindings< BindingsT, KeyList< KeyTs... > >
 
struct  NodeObserver
 
struct  NodeTiming
 Wall time for attempted node work, independently of later cache or Newton acceptance. More...
 
struct  NoGraphObservers
 Default high-level binding adds no observation storage, timers, or callback work. More...
 
class  Observers
 Own registrations; execution state lasts for one invocation and is never part of the numerical cache. More...
 
struct  PreparationFailure
 
struct  PreparationReport
 
class  ProjectedSnapshot
 
struct  ResolveKeys
 
struct  ResolveKeys< BindingsT, KeyList< KeyTs... > >
 
class  Resource
 
struct  SteadyNodeClock
 Read monotonic elapsed wall time without changing physical computations. More...
 
struct  ValueSnapshot
 Default tracking owns an exact value copy; noncopyable resources supply another policy. More...
 

Concepts

concept  IsBinding
 
concept  IsBindings
 
concept  BindingsWithBinding
 
concept  IsComputation
 
concept  CompatibleComputations
 A computational graph needs unique producers, valid input ownership, and no cycles.
 
concept  IsComputationGraph
 
concept  IsDependencyContext
 
concept  CanPrepare
 
concept  ComputationGraphFor
 
concept  IsKeyList
 
concept  SatisfiesKeyList
 
concept  ContainsKey
 Test exact key membership, rejecting malformed and duplicate-key lists.
 
concept  NodeObserverCallbacks
 Completion must be safe during stack unwinding and receives the state created by the before hook.
 
concept  KeyedNodeObserverCallbacks
 An all-node callback receives the compiled result identity before creating its invocation state.
 
concept  ObserversFor
 Reject unknown nodes, nonexistent edges, and callbacks that cannot observe the graph's immutable values.
 
concept  IsResource
 
concept  SnapshotPolicyFor
 
concept  NodeTimingClock
 Restrict injected clocks to ordinary arithmetic chrono values safe in a closing callback.
 

Typedefs

template<typename BindingsT, typename KeyT>
using bound_type_t = BoundType<BindingsT, KeyT>::target_type
 
template<typename... KeyTs>
using InputList = KeyList<KeyTs...>
 Computation arguments are supplied in this key order.
 
template<typename... KeyTs>
using RequestedResults = KeyList<KeyTs...>
 Preparing these results also prepares their required intermediate computations.
 
template<typename BindingsT, typename KeysT>
using ResolvedTargets = ResolveKeys<BindingsT, std::remove_cvref_t<KeysT>>::type
 
template<IsKeyList... Lists>
using CombinedKeyList = detail::MergeKeyLists<KeyList<>, std::remove_cvref_t<Lists>...>::type
 Combine requirements in first-appearance order, retaining distinct keys with shared targets.
 

Enumerations

enum class  NodeOutcome { completed , rejected , exception }
 Describe a node invocation, independently of whether the whole graph request is later accepted. More...
 
enum class  PreparationMode { reuse_unchanged , rebuild }
 
enum class  PreparationStatus { not_required , reused , computed }
 

Functions

template<typename KeyT, IsKeyList InputsT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto make_computation (FunctionT &&function)
 Attach an output key and ordered input keys to a lambda, function, or other callable.
 
template<typename KeyT, IsKeyList InputsT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto make_owning_computation (FunctionT &&function)
 Supply immutable shared handles to computed prerequisites so results can retain them without copying.
 
template<typename ErrorT = std::string, IsComputationGraph GraphT, IsDependencyContext ContextT, typename ObserversT = Observers<>>
requires CanPrepare<GraphT, ContextT, ErrorT> && ObserversFor<ObserversT, GraphT, ContextT> && std::constructible_from<std::remove_cvref_t<GraphT>, GraphT> && std::constructible_from<std::remove_cvref_t<ObserversT>, ObserversT>
auto make_computation_cache (GraphT &&graph, const ContextT &, ObserversT &&observers=ObserversT{})
 Fix the graph's source types without retaining the supplied context or evaluating any computations.
 
template<typename ErrorT = std::string, IsDependencyContext ContextT, typename... Computations>
requires CompatibleComputations<Computations...> && (std::constructible_from<std::remove_cvref_t<Computations>, Computations> && ...) && CanPrepare<ComputationGraph<std::remove_cvref_t<Computations>...>, ContextT, ErrorT>
auto make_computation_cache (const ContextT &context, Computations &&... computations)
 Build a checked graph and an empty cache directly from named computations.
 
template<typename... Computations>
requires CompatibleComputations<Computations...> && (std::constructible_from<std::remove_cvref_t<Computations>, Computations> && ...)
auto make_computation_graph (Computations &&... computations)
 Reject duplicate producers and cyclic computational graphs at the declaration site.
 
template<typename... Resources>
requires (IsResource<Resources> && ...) && misc::traits::all_unique_types_v<typename std::remove_cvref_t<Resources>::Key...>
auto make_dependency_context (Resources &&... resources)
 Build a context whose schema follows directly from its resource keys and types.
 
template<IsDependencyContext... Contexts>
requires (detail::combinable_resources(misc::concepts::ConcatT<typename Contexts::Resources...>{}))
auto combine_dependency_contexts (const Contexts &... contexts)
 Copy disjoint resources and their tracking policies into one context; borrowed objects retain their original lifetime.
 
template<typename KeyT, typename KeysT>
requires ContainsKey<KeyT, KeysT>
consteval std::size_t key_index ()
 Locate a declared key in its ordered list; absent keys are rejected at compile time.
 
template<typename KeyT, typename BeforeT, typename AfterT>
requires NodeObserverCallbacks<std::decay_t<BeforeT>, std::decay_t<AfterT>> && std::constructible_from<std::decay_t<BeforeT>, BeforeT> && std::constructible_from<std::decay_t<AfterT>, AfterT>
auto observe_node (BeforeT &&before, AfterT &&after)
 Bind before/after callbacks to a result key; callback captures determine any external storage lifetime.
 
template<typename BeforeT, typename AfterT>
requires std::constructible_from<std::decay_t<BeforeT>, BeforeT> && std::constructible_from<std::decay_t<AfterT>, AfterT>
auto observe_nodes (BeforeT &&before, AfterT &&after)
 Observe all executed nodes; cache construction checks the callback contract for every result key.
 
template<typename InputT, typename ConsumerT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto observe_edge (FunctionT &&function)
 Bind a read-only callback to one input of one consumer; graph construction validates the edge and value type.
 
template<typename... Registrations>
requires (detail::is_observer_v<std::remove_cvref_t<Registrations>> && ...) && (std::constructible_from<std::remove_cvref_t<Registrations>, Registrations> && ...)
auto make_observers (Registrations &&... observers)
 Collect any number of registrations, including several observers of the same node or edge.
 
template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto own (ValueT &&value, PolicyT policy={})
 Store a value in the context; rvalues transfer ownership and lvalues are copied.
 
template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto borrow (ValueT &value, PolicyT policy={})
 Bind an existing object whose lifetime must cover every use of the context.
 
template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto borrow (const ValueT &&, PolicyT={})=delete
 Borrowed storage must never refer to a temporary, including a const temporary.
 
template<typename FunctionT>
auto track_by (FunctionT &&function)
 Select the state that determines whether a source needs recomputation.
 
template<typename PolicyT, typename ValueT>
requires SnapshotPolicyFor<PolicyT, ValueT>
const void * source_identity (const PolicyT &policy, const ValueT &value)
 Views may identify their underlying resource; ordinary sources retain object identity.
 
template<NodeTimingClock Clock = SteadyNodeClock>
auto time_graph_nodes (GraphTiming &timing, Clock clock={})
 Opt into node timings; a custom clock supports deterministic accounting tests without sleeps.
 

Variables

template<typename T>
constexpr bool is_bindings_v = false
 
template<typename... BindingTs>
constexpr bool is_bindings_v< Bindings< BindingTs... > > = misc::traits::all_unique_types_v<typename BindingTs::Key...>
 
template<IsBindings BindingsT, typename KeyT>
constexpr bool has_binding_v = HasBinding<BindingsT, KeyT>::value
 
template<typename T>
constexpr bool is_computation_v = false
 
template<typename KeyT, typename InputsT, typename FunctionT, bool OwnsInputs>
constexpr bool is_computation_v< Computation< KeyT, InputsT, FunctionT, OwnsInputs > > = true
 
template<typename T>
constexpr bool is_computation_graph_v = false
 
template<typename... Computations>
constexpr bool is_computation_graph_v< ComputationGraph< Computations... > > = true
 
template<typename T>
constexpr bool is_dependency_context_v = false
 
template<typename... Resources>
constexpr bool is_dependency_context_v< DependencyContext< Resources... > > = true
 
template<typename ParentT, typename KeysT>
constexpr bool is_dependency_context_v< DependencyContextView< ParentT, KeysT > > = true
 
template<typename T>
constexpr bool is_key_list_v = false
 
template<typename... KeyTs>
constexpr bool is_key_list_v< KeyList< KeyTs... > > = misc::traits::all_unique_types_v<KeyTs...>
 
template<IsKeyList KeysT>
constexpr std::size_t key_count_v = detail::KeyListSize<std::remove_cvref_t<KeysT>>::value
 Count distinct declared keys without constructing their associated values.
 
std::unordered_map< PreparationStatus, std::string_view > preparation_status_name_map = meta::enum_to_enum_string_map<PreparationStatus>()
 
std::unordered_map< PreparationMode, std::string_view > preparation_mode_name_map = meta::enum_to_enum_string_map<PreparationMode>()
 
template<typename T>
constexpr bool is_resource_v = false
 
template<typename KeyT, typename StorageT, typename PolicyT>
constexpr bool is_resource_v< Resource< KeyT, StorageT, PolicyT > > = true
 

Detailed Description

Computational Graphs

Demonstration code for how to use the SERiF computational graph system The broad idea here is that there are many calculations which depend on each other but which may not necessarily always need to be recomputed just because another part of the model has changed. We model this as a combination of an acyclic computational graph, defined at compile time, and a runtime cache of values. The general workflow is that a developer defines the "context" of the computational graph, think of this as all of the inputs to the graph, or maybe more specifically, anything that could change due to some external event (e.g. a time step, a newton step, etc...) This context is probably the most CS intensive part of this code as the developer needs to think about lifetimes and ownership.

Context Contexts are made with the make_dependency_context function, this accepts a variadic pack of bindings between a type and a runtime value. You can generate these yourself using the binding functions and types; however, we provide two convenience wrappers which generally developers should consider using.

  • borrow: Used to bind a type to a reference to a value. This is useful for values which are owned by the caller and which the caller will manage the lifetime of (takes an lvalue).
  • own: Used to bind a type to a value which is owned by the context (copies an lvalue or moves an rvalue) Each of these functions accepts a type as a template parameter and a runtime value as an argument. The type is used as an ID, this is key to understand, if we write
    double x{1.0};
    Definition binding.hpp:7
    auto make_dependency_context(Resources &&... resources)
    Build a context whose schema follows directly from its resource keys and types.
    Definition dependency_context.hpp:101
    auto borrow(ValueT &value, PolicyT policy={})
    Bind an existing object whose lifetime must cover every use of the context.
    Definition resource.hpp:68

we are not saying that x is of type keys::Input, this is clearly not the case. Rather, we are registering in the computational graph a binding between the type keys::Input and the runtime value x. Think of this as naming the various inputs to the graph.

Computations After defining a context we can define a computation, each computation defines a node, while its ordered input keys define the incoming edges. Consider the following example (assuming the context from above):

[](const double _x) -> double {
return _x * _x;
}
);
auto make_computation(FunctionT &&function)
Attach an output key and ordered input keys to a lambda, function, or other callable.
Definition computation.hpp:44

what we have defined here is a node which takes a single input tagged keys::Input and produces an output tagged as keys::Output. The input key declares an edge from that source to this node. Other nodes can use keys::Output as an input, and a successfully prepared result can be read with get or retained with share. These connections allow us to form a larger graph. Consider now the following code

struct tags {
struct X{};
struct Y{};
struct Output1{};
struct Output2{};
};
double x{1.0};
double y{2.0};
[](const double _x) -> double {
return _x * _x;
}
);
[](const double _x, const double _y) -> double {
return _x + _y;
}
);

we have now defined two computations, the first takes a single input, whichever input is tagged as tags::X and produces an output tagged as tags::Output1. The second computation takes two inputs, the first is the output of the first computation (lookup by the tag) and the second is whichever input is tagged as tags::Y, and produces an output tagged as tags::Output2. Note that the order of arguments to the lambda must be the same as the order of the tags in the InputList, the dependencies module will automatically order arguments based on the InputList. There is type checking to ensure that the types match, but if you have two inputs of the same type that are flipped there is no way for the system to inspect that and warn you. Further, depending on your compiler and flags there may be implicit casting between convertable types (e.g. int <-> double).

Todo
We may want to remove the ability to have implicit casting between types, this is a bit of a footgun and may lead to subtle bugs.
Note
This is primary goal of this system, split computations into small pieces with the ability to cache intermediate results and reuse as many of those intermediate results as we can can prove is safe to do. The whole reason this system is so complex is that very purpose. There is a fundamental problem with high dimensional stellar models, they are always going to be slow, therefore we need to accept some degree of complexity in order to make them tractable.

Computation Cache Once we have the computations we need to connect them together, generally use the helper function make_computation_cache which takes a context and a variadic pack of computations. There are a lot of compile time checks which run to ensure that the graph is valid, the context describes what is needed to compute the graph, and that each computation is valid. Generally if a static analysis error or compile error pops up here it probably means there is a mistake in the definition of the context or the computations. I've tried to make these errors as clear as possible; however, there is only so much that you can do with the C++ compiler. I recommend first checking, probably with a drawn-out diagram, that all the tags are correct and what you expect.

A developer can also choose to use the make_computation_graph function to explicitly name a graph. This is useful when naming or reusing a collection of computations (make_computation_cache calls make_computation_graph and then fixes the source types from the supplied context without retaining the context). Now consider the following code assuming the context and computations from above:

auto graph_cache = make_computation_cache(context, func1, func2);
auto make_computation_cache(GraphT &&graph, const ContextT &, ObserversT &&observers=ObserversT{})
Fix the graph's source types without retaining the supplied context or evaluating any computations.
Definition computation_cache.hpp:318

At this point we have a cache which we can access various parts of; however, no computations have been run yet. To run a computation we must call try_prepare.

try_prepare returns std::expected: ordinary rejection is a value, and no candidate results or snapshots are published on failure. Exceptions from a callable or snapshot policy propagate with the same cache protection. Previously retained results remain valid, but get and share require a successful current preparation. Always check the report before reading results.

try_prepare takes the context and evaluates the requested nodes and their prerequisites, reusing unchanged results. By default every result is requested, so the first call evaluates the entire graph. RequestedResults can restrict evaluation to a branch.

auto report = graph_cache.try_prepare(context);
if (!report) {
return; // Handle report.error() before reading the cache.
}
double func1_result = graph_cache.template get<tags::Output1>();
double func2_result = graph_cache.template get<tags::Output2>();
auto func1_status = report->template status<tags::Output1>();
auto func2_status = report->template status<tags::Output2>();
std::string_view func1_status_string = preparation_status_name_map[func1_status]; // note this is an inline map defined in serif::utils::dependencies
std::string_view func2_status_string = preparation_status_name_map[func2_status];
std::println("Func1 Result: {}, Func2 Result: {}, Func1 Status: {}, Func2 Status: {}", func1_result, func2_result, func1_status_string, func2_status_string);
std::unordered_map< PreparationStatus, std::string_view > preparation_status_name_map
Definition preparation.hpp:23

Now what we could do is change only one part of the input context and call try_prepare again. Lets say we change only y, such that only func2 is stale.

y = 3.0;
report = graph_cache.try_prepare(context);
if (!report) {
return; // Handle report.error() before reading the cache.
}
double func1_result = graph_cache.template get<tags::Output1>();
double func2_result = graph_cache.template get<tags::Output2>();
auto func1_status = report->template status<tags::Output1>();
auto func2_status = report->template status<tags::Output2>();
std::string_view func1_status_string = preparation_status_name_map[func1_status]; // note this is an inline map defined in serif::utils::dependencies
std::string_view func2_status_string = preparation_status_name_map[func2_status];
std::println("Func1 Result: {}, Func2 Result: {}, Func1 Status: {}, Func2 Status: {}", func1_result, func2_result, func1_status_string, func2_status_string);

Typedef Documentation

◆ bound_type_t

template<typename BindingsT, typename KeyT>
using serif::utils::dependencies::bound_type_t = BoundType<BindingsT, KeyT>::target_type

◆ CombinedKeyList

template<IsKeyList... Lists>
using serif::utils::dependencies::CombinedKeyList = detail::MergeKeyLists<KeyList<>, std::remove_cvref_t<Lists>...>::type

Combine requirements in first-appearance order, retaining distinct keys with shared targets.

◆ InputList

template<typename... KeyTs>
using serif::utils::dependencies::InputList = KeyList<KeyTs...>

Computation arguments are supplied in this key order.

◆ RequestedResults

template<typename... KeyTs>
using serif::utils::dependencies::RequestedResults = KeyList<KeyTs...>

Preparing these results also prepares their required intermediate computations.

◆ ResolvedTargets

template<typename BindingsT, typename KeysT>
using serif::utils::dependencies::ResolvedTargets = ResolveKeys<BindingsT, std::remove_cvref_t<KeysT>>::type

Enumeration Type Documentation

◆ NodeOutcome

Describe a node invocation, independently of whether the whole graph request is later accepted.

Enumerator
completed 
rejected 
exception 

◆ PreparationMode

Enumerator
reuse_unchanged 
rebuild 

◆ PreparationStatus

Enumerator
not_required 
reused 
computed 

Function Documentation

◆ borrow() [1/2]

template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto serif::utils::dependencies::borrow ( const ValueT && ,
PolicyT = {} )
delete

Borrowed storage must never refer to a temporary, including a const temporary.

◆ borrow() [2/2]

template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto serif::utils::dependencies::borrow ( ValueT & value,
PolicyT policy = {} )
nodiscard

Bind an existing object whose lifetime must cover every use of the context.

◆ combine_dependency_contexts()

template<IsDependencyContext... Contexts>
requires (detail::combinable_resources(misc::concepts::ConcatT<typename Contexts::Resources...>{}))
auto serif::utils::dependencies::combine_dependency_contexts ( const Contexts &... contexts)
nodiscard

Copy disjoint resources and their tracking policies into one context; borrowed objects retain their original lifetime.

◆ key_index()

template<typename KeyT, typename KeysT>
requires ContainsKey<KeyT, KeysT>
std::size_t serif::utils::dependencies::key_index ( )
nodiscardconsteval

Locate a declared key in its ordered list; absent keys are rejected at compile time.

◆ make_computation()

template<typename KeyT, IsKeyList InputsT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto serif::utils::dependencies::make_computation ( FunctionT && function)
nodiscard

Attach an output key and ordered input keys to a lambda, function, or other callable.

◆ make_computation_cache() [1/2]

template<typename ErrorT = std::string, IsDependencyContext ContextT, typename... Computations>
requires CompatibleComputations<Computations...> && (std::constructible_from<std::remove_cvref_t<Computations>, Computations> && ...) && CanPrepare<ComputationGraph<std::remove_cvref_t<Computations>...>, ContextT, ErrorT>
auto serif::utils::dependencies::make_computation_cache ( const ContextT & context,
Computations &&... computations )
nodiscard

Build a checked graph and an empty cache directly from named computations.

◆ make_computation_cache() [2/2]

template<typename ErrorT = std::string, IsComputationGraph GraphT, IsDependencyContext ContextT, typename ObserversT = Observers<>>
requires CanPrepare<GraphT, ContextT, ErrorT> && ObserversFor<ObserversT, GraphT, ContextT> && std::constructible_from<std::remove_cvref_t<GraphT>, GraphT> && std::constructible_from<std::remove_cvref_t<ObserversT>, ObserversT>
auto serif::utils::dependencies::make_computation_cache ( GraphT && graph,
const ContextT & ,
ObserversT && observers = ObserversT{} )
nodiscard

Fix the graph's source types without retaining the supplied context or evaluating any computations.

◆ make_computation_graph()

template<typename... Computations>
requires CompatibleComputations<Computations...> && (std::constructible_from<std::remove_cvref_t<Computations>, Computations> && ...)
auto serif::utils::dependencies::make_computation_graph ( Computations &&... computations)
nodiscard

Reject duplicate producers and cyclic computational graphs at the declaration site.

◆ make_dependency_context()

template<typename... Resources>
requires (IsResource<Resources> && ...) && misc::traits::all_unique_types_v<typename std::remove_cvref_t<Resources>::Key...>
auto serif::utils::dependencies::make_dependency_context ( Resources &&... resources)
nodiscard

Build a context whose schema follows directly from its resource keys and types.

◆ make_observers()

template<typename... Registrations>
requires (detail::is_observer_v<std::remove_cvref_t<Registrations>> && ...) && (std::constructible_from<std::remove_cvref_t<Registrations>, Registrations> && ...)
auto serif::utils::dependencies::make_observers ( Registrations &&... observers)
nodiscard

Collect any number of registrations, including several observers of the same node or edge.

◆ make_owning_computation()

template<typename KeyT, IsKeyList InputsT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto serif::utils::dependencies::make_owning_computation ( FunctionT && function)
nodiscard

Supply immutable shared handles to computed prerequisites so results can retain them without copying.

Note
Every input must be produced by this graph. Context sources remain borrowed and cannot be retained this way. Resources borrowed inside a prerequisite must still outlive their use; the handle owns only the computed result.

◆ observe_edge()

template<typename InputT, typename ConsumerT, typename FunctionT>
requires std::constructible_from<std::decay_t<FunctionT>, FunctionT>
auto serif::utils::dependencies::observe_edge ( FunctionT && function)
nodiscard

Bind a read-only callback to one input of one consumer; graph construction validates the edge and value type.

◆ observe_node()

template<typename KeyT, typename BeforeT, typename AfterT>
requires NodeObserverCallbacks<std::decay_t<BeforeT>, std::decay_t<AfterT>> && std::constructible_from<std::decay_t<BeforeT>, BeforeT> && std::constructible_from<std::decay_t<AfterT>, AfterT>
auto serif::utils::dependencies::observe_node ( BeforeT && before,
AfterT && after )
nodiscard

Bind before/after callbacks to a result key; callback captures determine any external storage lifetime.

◆ observe_nodes()

template<typename BeforeT, typename AfterT>
requires std::constructible_from<std::decay_t<BeforeT>, BeforeT> && std::constructible_from<std::decay_t<AfterT>, AfterT>
auto serif::utils::dependencies::observe_nodes ( BeforeT && before,
AfterT && after )
nodiscard

Observe all executed nodes; cache construction checks the callback contract for every result key.

◆ own()

template<typename KeyT, typename ValueT, typename PolicyT = ValueSnapshot>
auto serif::utils::dependencies::own ( ValueT && value,
PolicyT policy = {} )
nodiscard

Store a value in the context; rvalues transfer ownership and lvalues are copied.

◆ source_identity()

template<typename PolicyT, typename ValueT>
requires SnapshotPolicyFor<PolicyT, ValueT>
const void * serif::utils::dependencies::source_identity ( const PolicyT & policy,
const ValueT & value )
nodiscard

Views may identify their underlying resource; ordinary sources retain object identity.

◆ time_graph_nodes()

template<NodeTimingClock Clock = SteadyNodeClock>
auto serif::utils::dependencies::time_graph_nodes ( GraphTiming & timing,
Clock clock = {} )
nodiscard

Opt into node timings; a custom clock supports deterministic accounting tests without sleeps.

◆ track_by()

template<typename FunctionT>
auto serif::utils::dependencies::track_by ( FunctionT && function)
nodiscard

Select the state that determines whether a source needs recomputation.

Variable Documentation

◆ has_binding_v

template<IsBindings BindingsT, typename KeyT>
bool serif::utils::dependencies::has_binding_v = HasBinding<BindingsT, KeyT>::value
inlineconstexpr

◆ is_bindings_v

template<typename T>
bool serif::utils::dependencies::is_bindings_v = false
inlineconstexpr

◆ is_bindings_v< Bindings< BindingTs... > >

template<typename... BindingTs>
bool serif::utils::dependencies::is_bindings_v< Bindings< BindingTs... > > = misc::traits::all_unique_types_v<typename BindingTs::Key...>
inlineconstexpr

◆ is_computation_graph_v

template<typename T>
bool serif::utils::dependencies::is_computation_graph_v = false
inlineconstexpr

◆ is_computation_graph_v< ComputationGraph< Computations... > >

template<typename... Computations>
bool serif::utils::dependencies::is_computation_graph_v< ComputationGraph< Computations... > > = true
inlineconstexpr

◆ is_computation_v

template<typename T>
bool serif::utils::dependencies::is_computation_v = false
inlineconstexpr

◆ is_computation_v< Computation< KeyT, InputsT, FunctionT, OwnsInputs > >

template<typename KeyT, typename InputsT, typename FunctionT, bool OwnsInputs>
bool serif::utils::dependencies::is_computation_v< Computation< KeyT, InputsT, FunctionT, OwnsInputs > > = true
inlineconstexpr

◆ is_dependency_context_v

template<typename T>
bool serif::utils::dependencies::is_dependency_context_v = false
inlineconstexpr

◆ is_dependency_context_v< DependencyContext< Resources... > >

template<typename... Resources>
bool serif::utils::dependencies::is_dependency_context_v< DependencyContext< Resources... > > = true
inlineconstexpr

◆ is_dependency_context_v< DependencyContextView< ParentT, KeysT > >

template<typename ParentT, typename KeysT>
bool serif::utils::dependencies::is_dependency_context_v< DependencyContextView< ParentT, KeysT > > = true
inlineconstexpr

◆ is_key_list_v

template<typename T>
bool serif::utils::dependencies::is_key_list_v = false
inlineconstexpr

◆ is_key_list_v< KeyList< KeyTs... > >

template<typename... KeyTs>
bool serif::utils::dependencies::is_key_list_v< KeyList< KeyTs... > > = misc::traits::all_unique_types_v<KeyTs...>
inlineconstexpr

◆ is_resource_v

template<typename T>
bool serif::utils::dependencies::is_resource_v = false
inlineconstexpr

◆ is_resource_v< Resource< KeyT, StorageT, PolicyT > >

template<typename KeyT, typename StorageT, typename PolicyT>
bool serif::utils::dependencies::is_resource_v< Resource< KeyT, StorageT, PolicyT > > = true
inlineconstexpr

◆ key_count_v

template<IsKeyList KeysT>
std::size_t serif::utils::dependencies::key_count_v = detail::KeyListSize<std::remove_cvref_t<KeysT>>::value
inlineconstexpr

Count distinct declared keys without constructing their associated values.

◆ preparation_mode_name_map

std::unordered_map<PreparationMode, std::string_view> serif::utils::dependencies::preparation_mode_name_map = meta::enum_to_enum_string_map<PreparationMode>()
inline

◆ preparation_status_name_map

std::unordered_map<PreparationStatus, std::string_view> serif::utils::dependencies::preparation_status_name_map = meta::enum_to_enum_string_map<PreparationStatus>()
inline