Graph structure#
See The Graph and Socket values, enumerations, validators for how these classes work together.
-
class InputSocket : public ng::Socket
Public Functions
-
InputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::string &value = "", bool linkable = true, const std::set<std::string> &allowed_values = {}, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {}, const std::set<qualifier_t> &on_value_changed_callbacks = {})
-
bool set_value(const std::string &value)
Sets the value if it is allowed (see is_allowed_value). Validators are not checked here (see check_validity).
- Returns:
true if the value was accepted.
-
inline void set_allowed_values(const std::set<std::string> &values)
-
inline void set_linkable(bool linkable)
-
inline const std::string &get_value() const
-
inline const std::set<std::string> &get_allowed_values() const
-
inline bool is_linkable() const
-
inline bool is_enum() const
-
inline const std::set<qualifier_t> &get_on_value_changed_callbacks() const
-
inline void register_on_value_changed_callback(const qualifier_t &cb)
-
bool is_allowed_value(const std::string &value) const
A value is allowed if the socket has no whitelist, or if the value is in the whitelist.
-
bool check_validity(const std::string &value) const
Checks the value against the validators registered (ValidatorsRegistry) for the types of this socket. The value is valid if no validator is registered for any of the socket’s types, or if at least one of the registered validators accepts it.
-
void trigger_on_added_link_callbacks(Graph &graph, Node &node_from, OutputSocket &from, Node &node_to)
-
void trigger_on_broken_link_callbacks(Graph &graph, Node &node_from, OutputSocket &from, Node &node_to, LinkBreakReason reason)
-
InputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::string &value = "", bool linkable = true, const std::set<std::string> &allowed_values = {}, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {}, const std::set<qualifier_t> &on_value_changed_callbacks = {})
-
class OutputSocket : public ng::Socket
Public Functions
-
OutputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {})
-
void trigger_on_added_link_callbacks(Graph &graph, Node &node_from, Node &node_to, InputSocket &to)
-
void trigger_on_broken_link_callbacks(Graph &graph, Node &node_from, Node &node_to, InputSocket &to, LinkBreakReason reason)
-
OutputSocket(const std::string &name = "", const socket_id_t &id = null_socket, socket_t type = null_socket_type, bool active = true, const std::set<qualifier_t> &on_added_link_callbacks = {}, const std::set<qualifier_t> &on_broken_link_callbacks = {})
-
class Node
Instance of a node in a graph. The node only knows the IDs of its sockets, the sockets themselves are owned by the Graph.
Public Functions
-
Node(const std::string &name = "", const node_id_t &id = null_node, const qualifier_t &qualifier = null_qualifier, const std::set<socket_id_t> &input_sockets = {}, const std::set<socket_id_t> &output_sockets = {}, bool proxy = false)
-
inline void set_name(const std::string &name)
-
inline void set_proxy(bool proxy)
-
inline const std::string &get_name() const
-
inline const node_id_t &get_id() const
-
inline const qualifier_t &get_qualifier() const
-
inline const std::set<socket_id_t> &get_input_sockets() const
-
inline const std::set<socket_id_t> &get_output_sockets() const
-
inline bool is_proxy() const
-
inline std::size_t n_input_sockets() const
-
inline std::size_t n_output_sockets() const
-
inline bool has_input_socket(const socket_id_t &socket_id) const
-
inline bool has_output_socket(const socket_id_t &socket_id) const
-
bool register_input_socket(const socket_id_t &socket_id)
- Returns:
true if the socket was not already registered.
-
bool register_output_socket(const socket_id_t &socket_id)
-
bool remove_input_socket(const socket_id_t &socket_id)
- Returns:
true if the socket was registered.
-
bool remove_output_socket(const socket_id_t &socket_id)
Public Static Functions
-
static std::size_t make_random_id()
- Returns:
A random number in [1, MAX_NODE_RANDOM_ID].
-
static void seed_random_ids(uint32_t seed)
Re-seeds the random IDs generator, to make the generated node IDs reproducible.
-
Node(const std::string &name = "", const node_id_t &id = null_node, const qualifier_t &qualifier = null_qualifier, const std::set<socket_id_t> &input_sockets = {}, const std::set<socket_id_t> &output_sockets = {}, bool proxy = false)
-
class NodeDefinition
Blueprint of a node type, registered in the NodesRegistry under its qualifier. Graph::add_node copies its sockets into the graph to create a new Node instance.
Public Functions
-
NodeDefinition() = default
-
NodeDefinition(const qualifier_t &qualifier, const std::set<InputSocket> &input_sockets, const std::set<OutputSocket> &output_sockets, const std::string &default_name)
-
inline const qualifier_t &get_qualifier() const
-
inline const std::set<InputSocket> &get_input_sockets() const
-
inline const std::set<OutputSocket> &get_output_sockets() const
-
inline const std::string &get_default_name() const
-
NodeDefinition() = default
-
class Graph
Public Types
-
using input_sockets_t = std::map<socket_uuid_t, InputSocket>
-
using output_sockets_t = std::map<socket_uuid_t, OutputSocket>
-
using links_t = std::set<link_t>
-
using interface_t = std::map<socket_uuid_t, InterfaceProperties>
Public Functions
-
Graph(std::string name = "", nodes_t nodes = {}, links_t links = {}, input_sockets_t input_sockets = {}, output_sockets_t output_sockets = {}, interface_t parameters = {}, interface_t results = {})
-
inline void set_name(const std::string &name)
-
inline void set_qualifier(const qualifier_t &q)
-
inline const std::string &get_name() const
-
inline const std::optional<qualifier_t> &get_qualifier() const
-
inline const input_sockets_t &get_input_sockets() const
-
inline const output_sockets_t &get_output_sockets() const
-
inline const nodes_t &get_nodes() const
-
inline const links_t &get_links() const
-
inline const interface_t &get_parameters() const
-
inline const interface_t &get_results() const
-
node_id_t add_node(const qualifier_t &node_qualifier)
- Returns:
The ID of the new node, or null_node if the node type is not registered.
-
node_id_t add_node(const char *node_qualifier)
-
inline bool has_node(const node_id_t &node_id) const
-
bool remove_node(const node_id_t &node_id)
Removes the node, its links, its sockets and their exposure in the interface.
- Returns:
false if the node doesn’t exist.
-
void disconnect_node(const node_id_t &node_id, LinkBreakReason reason = LinkBreakReason::Manual)
Breaks all the links going to or coming from the node.
-
void rename_node(const node_id_t &node_id, const std::string &name)
- Throws:
std::out_of_range – if the node doesn’t exist.
-
const InputSocket &get_input_socket(const socket_uuid_t &suuid) const
- Throws:
std::out_of_range – if the socket doesn’t exist.
-
const OutputSocket &get_output_socket(const socket_uuid_t &suuid) const
-
Status set_socket_value(const socket_uuid_t &suuid, const std::string &value)
Sets the value of an input socket, after checking the validators and the allowed values. The callbacks of the socket are triggered only if the value is accepted.
-
const std::string &get_socket_value(const socket_uuid_t &suuid) const
- Throws:
std::out_of_range – if the input socket doesn’t exist.
-
Status add_link(const socket_uuid_t &from, const socket_uuid_t &to)
Links an output socket to an input socket. If the input socket is already linked, the previous link is replaced. If the input socket is exposed as a parameter, it stops being exposed. Adding a link that already exists is a no-op returning Status::Ok.
-
bool break_link(const link_t &link)
- Returns:
false if the link doesn’t exist.
-
links_t::const_iterator find_link_by_input_socket(const socket_uuid_t &target) const
- Returns:
An iterator to the link targeting this input socket, or get_links().end().
-
inline bool is_linked(const socket_uuid_t &input) const
-
links_t get_input_links(const node_id_t &node_id) const
- Returns:
All the links whose destination is a socket of this node.
-
links_t get_output_links(const node_id_t &node_id) const
- Returns:
All the links whose source is a socket of this node.
-
Status expose_parameter(const socket_uuid_t &suuid, const socket_id_t &alias, std::string show_as = "")
Exposes an input socket as a parameter of the graph, so it becomes an input of the proxy nodes. Any link targeting this socket is broken.
- Parameters:
suuid – The socket to expose.
alias – The ID of the socket on the proxy nodes, must be unique among parameters.
show_as – The name of the socket on the proxy nodes. Defaults to the socket’s name.
-
bool remove_parameter(const socket_uuid_t &suuid)
-
Status expose_result(const socket_uuid_t &suuid, const socket_id_t &alias, std::string show_as = "")
Same as expose_parameter, for output sockets.
-
bool remove_result(const socket_uuid_t &suuid)
-
node_id_t add_proxy_node(const qualifier_t &graph_qualifier)
Adds a node representing another graph, loaded from the disk through the GraphManager. Its inputs are the parameters of that graph and its outputs are its results.
- Throws:
std::runtime_error – if the graph can’t be found.
- Returns:
The ID of the new node, or null_node if the graph tries to contain itself.
-
node_id_t add_proxy_node(const char *graph_qualifier)
-
std::set<node_id_t> get_source_nodes() const
- Returns:
The nodes that are not the destination of any link.
-
bool causes_cycle(const link_t &link) const
-
DepthProperties get_depth_properties() const
-
DepthProperties get_depth_properties(const links_t &links) const
-
struct DepthProperties
-
struct InterfaceProperties
How a socket is exposed in the interface (parameters or results) of a graph.
Public Members
-
std::string show_as
Name displayed for the socket of the proxy node.
-
socket_id_t socket_id
ID of the socket of the proxy node.
-
std::string show_as
-
using input_sockets_t = std::map<socket_uuid_t, InputSocket>
-
class GraphManager
Owns the graphs in memory and the “heads”: root folders on the disk where graphs are saved. A graph with the qualifier “a.b.c” is saved in “<head>/a/b/c.graph”.
Public Types
-
enum class Owner
Ordered from the most personal to the least personal: when saving, the most personal writable head is used.
Values:
-
enumerator User
-
enumerator Group
-
enumerator Global
-
enumerator Unknown
-
enumerator User
-
using head_id_t = std::size_t
-
using library_t = std::map<qualifier_t, head_id_t>
-
using heads_t = SmallMap<head_id_t, HeadProperties>
Public Functions
-
GraphManager(const GraphManager&) = delete
-
GraphManager &operator=(const GraphManager&) = delete
-
~GraphManager() = default
-
inline const library_t &get_library() const
-
inline const heads_t &get_heads() const
-
inline const Graph &get_graph(graph_id_t id) const
- Throws:
std::out_of_range – if the graph doesn’t exist.
-
inline Graph &get_graph(graph_id_t id)
-
inline bool has_graph(graph_id_t id) const
-
graph_id_t new_graph(const std::string &name = "")
-
bool close_graph(graph_id_t id)
- Returns:
false if the graph doesn’t exist.
-
head_id_t add_head(const std::filesystem::path &path, Owner owner = Owner::User)
Registers a new head and discovers the graphs it contains.
-
void refresh()
Re-discovers the graphs contained in all the readable heads.
-
bool exists(const qualifier_t &q) const
- Returns:
true if a graph with this qualifier exists in one of the heads.
-
Status save_graph(graph_id_t id)
Saves the graph in the most personal writable head.
-
Status save_graph(graph_id_t id, head_id_t head_id)
-
Graph raw_read(const qualifier_t &q) const
Reads a graph from the disk without registering it in the manager.
- Throws:
std::runtime_error – if the graph can’t be found or read.
-
graph_id_t load_graph(const qualifier_t &q, bool force = false)
Loads a graph from the disk and registers it in the manager. If it was already loaded and force is false, the ID of the graph in memory is returned.
- Throws:
std::runtime_error – if the graph can’t be found or read.
-
void reset()
Forgets everything: graphs in memory and heads. Mostly useful for tests.
Public Static Functions
-
static bool can_write(const std::filesystem::path &path)
-
static bool can_read(const std::filesystem::path &path)
-
static GraphManager &instance()
-
enum class Owner
-
template<typename DB>
class GraphRuntime Converts a graph into a flat sequence of operators, sorted by depth, and runs them. Proxy nodes are expanded recursively: their operators are inlined at their position. Unlinked inputs are parsed from the value of their socket.
Public Types
-
using operator_ptr_t = std::unique_ptr<operator_t>
-
using bindings_t = std::map<socket_id_t, data_id_t>
Public Functions
-
explicit GraphRuntime(const Graph &graph)
- Throws:
std::runtime_error – if an operator is missing, a proxy can’t be read or the graph contains a cycle.
-
explicit GraphRuntime(graph_id_t gid)
Builds the runtime of a graph owned by the GraphManager.
-
inline const std::vector<operator_ptr_t> &get_operators() const
-
inline const DB &get_data_bank() const
-
inline DB &get_data_bank()
-
inline const bindings_t &get_results() const
-
inline bool is_executed(std::size_t index) const
-
template<typename T>
inline std::optional<T> get_result(const socket_id_t &alias) const - Returns:
The value of a result of the graph, if it has been computed with this type.
-
template<typename T>
inline std::optional<T> get_result(const char *alias) const
-
bool run()
Runs all the operators in order. Stops at the first operator failing to pull, poll, process or push.
- Returns:
true if all the operators were executed.
-
using operator_ptr_t = std::unique_ptr<operator_t>
-
template<typename DB>
class Operator Runtime counterpart of a node: the object actually doing the computation. Each socket of the node is bound to an item of the data bank. The runtime calls, in this order: pull (read inputs), poll (ready?), process (compute), push (write outputs).
Public Types
-
using bindings_t = std::map<socket_id_t, data_id_t>
Public Functions
-
inline Operator(const std::string &name = "")
-
inline Operator(const bindings_t &bindings, const std::string &name = "")
-
virtual ~Operator() = default
-
inline const std::string &get_name() const
-
inline const bindings_t &get_bindings() const
-
inline data_id_t get_binding(const socket_id_t &socket) const
- Returns:
The data ID bound to the socket, or null_data.
-
inline data_id_t get_binding(const char *socket) const
-
inline void bind(const socket_id_t &socket, data_id_t id)
-
virtual bool pull(const DB &db) = 0
-
virtual bool poll() = 0
-
virtual bool push(DB &db) = 0
-
inline bool process()
-
using bindings_t = std::map<socket_id_t, data_id_t>
-
template<typename ...Ts>
class DataBank Storage of the data exchanged by operators at runtime. There is one pool per type, all the pools share the same IDs sequence so an ID identifies a single item. The ID 0 (null_data) is never attributed.
Public Functions
-
inline bool contains(data_id_t id) const
- Returns:
true if any pool contains this ID.
-
inline void erase(data_id_t id)
-
inline data_id_t reserve_id()
Reserves an ID that can later be filled with store.
-
inline data_id_t get_next_id() const
-
template<typename ...Args>
inline bool load(data_id_t id, std::variant<Args...> &var) const Fills var with the item id, using the first alternative of the variant having an item with this ID.
- Returns:
false if none of the alternatives has an item with this ID.
-
inline bool contains(data_id_t id) const