2 releases
0.1.1 | Nov 23, 2020 |
---|---|
0.1.0 | Oct 28, 2020 |
#543 in Concurrency
40KB
739 lines
Dager
Evolution of my last experiment, dagger[], which is the evolution of the first execution graph library asyncgraph. Dagger has an multithreaded executor that uses a theadpool. It is able to execute any execution DAG. 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
crate. So you can init a simple logger like simple_logger on startup and get pretty printed warnings from the graph, while its executed.
Building and running
First install Rust 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.
Dependencies
~585KB