# Dager Evolution of my last experiment, dagger[], which is the evolution of the first execution graph library [asyncgraph](https://gitlab.com/tendsinmende/asyncgraph). Dagger has an multithreaded executor that uses a theadpool. It is able to execute any execution [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph). However, it is your responibility that the graph makes sense. ## Design The principle of the graph is, that a node gets executed every time all of its inputs are ready. The execution of the node itself is scheduled via an executer that must be started by the user (see the examples). So if it can’t continue the work, the scheduler will automatically pause the thread and try to work on something else. Each node as an `Aggregator` "around" it. It waits for all inputs to be ready, executes the node, and sends this nodes output to the next nodes based on the currently set edges of this node. ## Safety Since the graph can change at any time, it can't be as type safe as a statically dispatched graph. Therefore, types are checked every time a edge is added to a node. An error is thrown if an edge has not the same input and output types of the two connecting nodes. However, if an edge successfully connects, the graph guarantees that the connection will last, and work. Obviously if you are build some unsound graph, the output will be unsound as well. For instance a graph that gets no input won't produce anything. Similarly a node where not all inputs are set won't fire ever. ## Implementing custom nodes So how hard is it to implement custom nodes? Well intentionally pretty easy, the following code implements float addition. However, this can be easily abstracted over all type `T` that implement `Add` as you can see in the `examples/math.rs` example. ``` struct AddFloat; impl Node for FloatAdd{ type InSig = (f32, f32); type OutSig = [f32; 1]; fn process(&self, input: Self::Inputs) -> Self::Outputs{ [input.0 + input.1] } } ``` ## Logging Since graphs are always difficult, the crate implements the [`log`](https://crates.io/crates/log) crate. So you can init a simple logger like [simple_logger](https://crates.io/crates/simple_logger) on startup and get pretty printed warnings from the graph, while its executed. ## Building and running First [install Rust](https://www.rust-lang.org/learn/get-started) and cargo on your platform. Then execute ``` cargo build --release ``` in the root to build the library. Similar to all rust/cargo projects several examples can be executed by ``` cargo run --example {example_name} ``` where `{example_name}` can be the following: - math (some simple calculation example) - looping_execution (some graph that gets executed) - self_executing (some graph that uses the `Executable` trait for all nodes that have no inputs) - dynamic_graph (a graph that gets changed at runtime to include or exclude some printer node) ## Documentation Documentation can be build locally via ``` cargo doc --open ``` Most code is documented. ## License The whole project is licensed under the Mozilla Public License, v. 2.0 A version of this license is included in the repository and a notice at the top of every code-file.