Files
oxydsp/oxydsp-flowgraph/src/graph.rs
2026-03-23 20:29:53 +01:00

179 lines
4.9 KiB
Rust

use std::thread::JoinHandle;
use crate::block::GraphableBlock;
#[macro_export]
macro_rules! flowgraph
{
($($x:ident),* $(,)?) =>
{
{
let mut flowgraph = FlowGraph::new();
$(
flowgraph.add_block($x);
)*
flowgraph
}
}
}
pub struct FlowGraph
{
blocks: Vec<Box<dyn GraphableBlock + Send + 'static>>,
}
impl FlowGraph
{
pub fn new() -> Self
{
FlowGraph { blocks: vec![] }
}
pub fn add_block<T: GraphableBlock + Send + 'static>(&mut self, block: T)
{
block.set_index(self.blocks.len());
self.blocks.push(Box::new(block));
}
pub fn run(mut self) -> JoinHandle<()>
{
self.populate_edges();
std::thread::spawn(move || {
'outer: loop
{
for x in self.blocks.iter_mut()
{
match x.work()
{
crate::block::BlockResult::Ok =>
{}
crate::block::BlockResult::Terminated =>
{ //break 'outer;
}
crate::block::BlockResult::Exit =>
{
println!("KILLING GRAPH");
break 'outer;
}
}
}
}
})
}
fn populate_edges(&mut self)
{
for block_index in 0..self.blocks.len()
{
let successors = self.blocks[block_index].get_successors();
for (output_index, succ_id) in successors.iter().enumerate()
{
let (tx, rx) =
self.blocks[block_index].create_anonymous_stream_for(output_index, 4096);
self.blocks[block_index].set_anonymous_out_stream(output_index, tx);
self.blocks[succ_id.block_index].set_anonymous_in_stream(succ_id.port_index, rx);
}
}
}
pub fn get_dot(&self) -> String
{
let mut node_string = String::new();
for (i, block) in self.blocks.iter().enumerate()
{
// Block name
// Input strings
let mut input_string = String::new();
let inputs = block.get_input_names();
let len = inputs.len();
if !inputs.is_empty()
{
input_string.push('{');
for (j, input) in inputs.iter().enumerate()
{
input_string.push_str(&format!("<i{}> {}", j, input));
if j != len - 1
{
input_string.push('|');
}
}
input_string.push_str("}|");
}
// Output strings
let mut output_string = String::new();
let outputs = block.get_output_names();
let len = outputs.len();
if !outputs.is_empty()
{
output_string.push_str("|{");
for (j, output) in outputs.iter().enumerate()
{
output_string.push_str(&format!("<o{}> {}", j, output));
if j != len - 1
{
output_string.push('|');
}
}
output_string.push('}');
}
node_string.push_str(&format!(
"{}_{} [label=\"{{ {} {} {} }}\"];\n",
block.get_block_name(),
i,
input_string,
block.get_block_name(),
output_string,
));
}
let mut edges_string = String::new();
for (i, block) in self.blocks.iter().enumerate()
{
let outputs = block.get_successors();
let output_types = block.get_output_type_names();
let block_name = block.get_block_name();
for (j, (output, output_type)) in outputs.iter().zip(output_types.iter()).enumerate()
{
let destination_block = output.block_index;
let destination_block_name = self.blocks[destination_block].get_block_name();
edges_string.push_str(&format!(
"{}_{}:o{} -> {}_{}:i{} [label=\"{}\"];\n",
block_name,
i,
j,
destination_block_name,
destination_block,
output.port_index,
output_type
));
}
}
format!(
"
digraph G {{
node [shape=record];
rankdir=TB;
{}
{}
}}
",
node_string, edges_string
)
}
}
impl Default for FlowGraph
{
fn default() -> Self
{
Self::new()
}
}