Shortcuts

Template Class Node

Class Documentation

template<size_t Alignment, size_t MinStorage = 72>
class ripple::Node

Implementation type of a node class, which defines an operation a graph which performs work.

It should be given an alignment which is a multiple of the cache line size so that there is no false sharing of nodes when they are used across threads.

There is a small amount of overhead in the nodes, but they are still cheap In order for the Node’s work to be any callable object, the abstract base class NodeExecutor pointer needs to be stores.

This is not really a problem in terms of storage overhead since ndoes are cache line aligned, and the 8 bytes are usually only a fraction of the cache line size, but it does reduce the available storage for the callable for the executor’s work and more importantly, the arguments for the callable. It is therefore only a problem if the callable has many arguments, or the arguments are large. If this is a problem, a compile time error will be generated, in which case the alignment of the Node can be increased by the cachline size.

Executing the Node’s work then requires invoking the stored callable through the base NodeExecutor class. Benchmarks have shown that the compiler is usually able to remove the virtual function indirection, and the performance is usually the same as a non inlined function call. The major drawback therefore is the loss of the ability for the compiler to inline.

However, the benchmarking also showed that the the cost is approximately 1.1ns for any body of work executed through the NodeExecutor vs 0.25ns for an inlined version. This cost is therfore pretty small, and worth the added flexibility of allowing nodes to have any signature.

The above limitations are also not significant, since the

correct use of nodes in the graph is to perform non trivial workloads. Even a node with a ~30ns workload only incurrs a ~2.5% overhead compared to if the Node’s work body was executed inline. Most work should be in the us to ms range anyway, making the overhead negligible.
Note

The benchmarks were also on very cheap nodes (with small workloads).

Template Parameters
  • Alignment: The aligment for the node.

  • MinStorage: The number of bytes of storage required for a node.

Public Functions

Node() noexcept = default

Default constructor.

~Node() noexcept = default

Default destructor.

Node(const Node &other) noexcept

Copy constructor which clones the executor and copies the rest of the node state.

Note

This will check against the executor being a nullptr in debug mode, in release there is not check and a null executor will likely cause a segfault.

Note

This could be expensive if the node has a lot of successors.

Note

This does not copy the node’s information. Information for a node is unique and should be allocated and set after copying a noce.

Parameters
  • other: The other node to copy into this node.

Node(Node &&other) noexcept

Move constructor which just calls the copy constructor for most of the node data, but moves the successors of the other node into this node.

Parameters
  • other: The other task to move from.

template<typename F, typename ...Args, non_node_enable_t<F> = 0>
Node(F &&callable, Args&&... args) noexcept

Constructs the node, creating its executor by storing the callable and the callable’s arguments in the additional storage for the node.

Note

This constructor is only enabled if F is not a Node.

Note

If the callable and its arguments will not fit into the node storage then this will fail at compile time and the size of the node will need to be increased.

Parameters
  • callable: The callable object to store.

  • args: The arguments to store.

Template Parameters
  • F: The type of the callable object.

  • Args: The type of the arguments for the callable.

auto operator=(const Node &other) noexcept -> Node&

Copy assignment overload which clones the executor and copies the node state.

Note

This will check against the other node’s executor being a nullptr in debug, but will likely cause a segfault in release.

Note

This does not copy the node information, which should be unique and therefore allocated and then set after copying the node.

Return

A reference to the new node.

Parameters
  • other: The other node to copy.

auto operator=(Node &&other) noexcept -> Node&

Move assignment overload which clones the executor, copies the other node state, moves the other node’s successors, and invalidates the other node.

Note

This will check against the other node’s executor being a nullptr in debug, in release it will likely cause a segfault.

Return

A reference to the new node.

Parameters
  • other: The other node to move from.

template<typename F, typename ...Args>
auto set_executor(F &&callable, Args&&... args) noexcept -> void

Sets the executor of the node to use the given callable and its args.

Note

This will check that there is enough space in the node storage for the callable and its arguments. If there is not enough space, a compile time error is generated with the required additional number of bytes.

Parameters
  • callable: The callable object to store.

  • args: The arguments to store.

Template Parameters
  • F: The type of the callable object.

  • Args: The type of the arguments for the callable.

auto try_run() noexcept -> bool

Tries to run the node.

Return

true if the node has no dependencies and therefore executes, otherwise returns false.

auto add_successor(Node &node) noexcept -> void

Add sthe given node as a successor for this node.

Parameters
  • node: The node to add as a successor to this node.

auto add_friend(typename NodeInfo::IdType friend_id) noexcept -> void

Adds the node with the given id as a friend of this node.

For example, if x is a friend of y, then y

uses x for an operation, and x cannot be modified by any operations on it until y has performed its operation.
Note

A friend node is a node which can execute in parallel with another node, but which is used by the other node for the other node’s operation, but is not modified by it.

Parameters
  • friend_id: The id of the friend to add.

auto friends() const noexcept -> typename NodeInfo::Friends&

Gets all friends for the node.

Return

A container of all friend node ids.

auto increment_num_dependents() noexcept -> void

Increments the number of dependents for the node.

auto name() const noexcept -> typename NodeInfo::Name

Gets the name of the node.

Return

the name of the node.

auto id() const noexcept -> typename NodeInfo::IdType

Gets the id of the node.

Return

The id of the node.

auto kind() const noexcept -> NodeKind

Gets the kind of the node.

Return

The kind of the node.

auto execution_kind() const noexcept -> ExecutionKind

Gets the execution target for the node.

Return

The kind of the execution target for the node.

auto num_dependents() const noexcept -> CounterValue

Gets the number of dependents for the node.

Return

The number of dependents for the node.

Docs

Access comprehensive developer documentation for Ripple

View Docs

Tutorials

Get tutorials to help with understand all features

View Tutorials

Examples

Find examples to help get started

View Examples