Crate rgraph [−] [src]
The rGaph crate:
This library provides the mechanisms to define a directed acyclic graph of tasks. Once the graph is generated, a solver object can be instantiated to execute any of the tasks defined. In order to satisfy the input of such task, all the producer tasks will be executed as well.
A task can be defined like you would define a function, it requires: - A name - A list of inputs, that well may be empty. - A list of outputs, which can be empty as well. - Body, executing the code necessary to produce the outputs out of the inputs.
The macro create_node!
will help you out with this task:
use rgraph::*; create_node!( task_name (a: u32, b : u32) -> (output: u32) { // return is done by assigning to the output variable output = a + b; } );
The body of the task will be executed by a move lambda, this enforces some guarantees. Nevertheless if the tasks need to execute some side effects, you may keep in mind that: - Objects need to be cloned into the task scope. - Only runtime borrowing can be checked at this point. - The Solver has no knowledge of data changes done via global access. It only tracks assets registered as inputs or outputs of the task. For this reason tasks may not be executed a second time as long as the inputs do not change. This may turn into side effects not happening because the requirements were not declared correctly.
Once the tasks are defined, you can bind the input assets to the output produced by other task or feed directly into the Solver.
use rgraph::*; let mut g = Graph::new(); g.add_node(create_node!( task1 () -> (out_asset: u32) { // .... task body out_asset = 1; } )); g.add_node(create_node!( task2 (in_asset : u32) -> () { // .... task body } )); g.bind_asset("task1::out_asset", "task2::in_asset").expect(" tasks and assets must exist");
Finally, to execute the Graph: - Create an assets cache object (which can be reused to execute the graph again) - Create a solver, to be used one single time and then dropped.
use rgraph::*; let mut g = Graph::new(); // ... create graph and bind the assets let mut cache = ValuesCache::new(); let mut solver = GraphSolver::new(&g, &mut cache); // terminal tasks are those which do not produce output // the following line will traverse the graph and execute all tasks needed // to satisfy the terminal tasks. solver.execute_terminals().unwrap();
Modules
printer |
Macros
asset_name | |
create_node |
Macro to generate a Node (Task). It requires: a name (as used in the solver to execute it), a set of inputs, a set of outputs, and a set of statements which are the body of the task |
Structs
Graph |
The graph class itself. It holds the static information about the tasks (Nodes) and how they depend on each other by waiting on resources (Assets) |
GraphSolver |
The graph solver is a transient object which can execute the tasks described in a graph. It is designed to be generated and dropped on every execution. |
Node |
Generic that stores the information required to execute arbitrary tasks
Please use |
Enums
GraphError |
Errors that may happen during Graph construction |
SolverError |
Errors that may happen during a Solver instance execution |
SolverStatus |
Type to differentiate cached tasks from executed ones |
Traits
Cache | |
Comparable |
this trait allows us to overload behavior for custom types in this manner comparison can be optimized or bypassed for custom types |
NodeRunner |
helper trait that hides heterogeneous tasks behind a common interface |
Type Definitions
ValuesCache |
type used to store results of executions and pass it to further solver instances |