lmflow/lib.rs
1//! A dataflow-graph compute engine.
2//!
3//! Computation is described as a directed graph: nodes are **kernels**, and **timestamped
4//! packets** flow along the edges. This crate is the engine itself — scheduling, worker threads,
5//! edge queues, topology validation and YAML parsing.
6//!
7//! # Two interfaces
8//!
9//! * **Rust API** — the public items of this crate ([`Graph`], [`Packet`], [`Kernel`], …).
10//! * **C ABI** — the [`ffi`] module, declared in `include/lmflow/flow.h`. This is the only
11//! *stable* interface, and it is what C, C++, Python and mobile hosts use.
12//!
13//! # Kernels are decoupled from the engine
14//!
15//! A kernel can be written in **Rust** ([`Kernel`] + [`register_kernel`]), in **C++** (the
16//! header-only `flow.hpp` sugar layer), or in **Python** (pybind11). All three register into one
17//! registry through the same function-pointer vtable, so the engine neither knows nor cares which
18//! language a kernel came from — and kernels written in different languages can be mixed freely
19//! in a single graph.
20//!
21//! This crate is a **pure-Rust engine by default**: it neither compiles nor bundles any C++, so
22//! `cargo add lmflow` needs no C++ toolchain. Kernels are always supplied explicitly by the host
23//! or by a linked kernel component; the engine itself only schedules them and never interprets
24//! payloads.
25//!
26//! # Running a graph
27//!
28//! ```
29//! use lmflow::{register_kernel, Graph, Kernel, KernelCtx, Packet, Timestamp};
30//!
31//! #[derive(Default)]
32//! struct Relay;
33//!
34//! impl Kernel for Relay {
35//! fn process(&mut self, context: &mut KernelCtx) -> lmflow::Result<()> {
36//! context.forward(0, 0)
37//! }
38//! }
39//!
40//! # fn main() -> lmflow::Result<()> {
41//! register_kernel::<Relay>("Relay")?;
42//! let graph = Graph::from_yaml(
43//! r#"
44//! nodes:
45//! - { name: relay, kernel: Relay, input_ports: [in], output_ports: [out] }
46//! input_ports: [in]
47//! output_ports: [out]
48//! "#,
49//! )?;
50//!
51//! let out = graph.add_poller("out")?;
52//! graph.start()?;
53//! graph.input("in")?.send(Packet::from_i64(21).at(Timestamp(0)))?;
54//!
55//! assert_eq!(out.next().and_then(|p| p.as_i64()), Some(21));
56//!
57//! graph.close_all_inputs();
58//! graph.wait_done()?;
59//! # Ok(())
60//! # }
61//! ```
62//!
63//! # Writing a kernel
64//!
65//! ```
66//! use lmflow::{register_kernel, Kernel, KernelCtx, Packet};
67//!
68//! #[derive(Default)]
69//! struct Double;
70//!
71//! impl Kernel for Double {
72//! fn process(&mut self, cc: &mut KernelCtx) -> lmflow::Result<()> {
73//! let v = cc.input(0).and_then(|p| p.as_i64()).unwrap_or(0);
74//! cc.emit(0, Packet::from_i64(v * 2))
75//! }
76//! }
77//!
78//! # fn main() -> lmflow::Result<()> {
79//! register_kernel::<Double>("Double")?; // once, before Graph::from_yaml
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! # Beyond this crate
85//!
86//! The lm-flow repository also carries 18 optional C++ kernels (`../cpp/kernels/`). They are built
87//! separately by CMake as `lmflow::kernels`; this crate never compiles or bundles C++.
88//!
89//! Full documentation, including the C/C++ and Python interfaces:
90//! <https://laomou.github.io/lm-flow/>. The authoritative design document — scheduling model,
91//! timestamp and termination semantics, lock ordering rules and the decision log — is
92//! `docs/design.md` (written in Chinese).
93
94mod buffer_pool;
95pub mod config;
96pub mod context;
97mod diagnostic;
98mod dot;
99pub mod executor;
100mod expand;
101pub mod ffi;
102pub mod graph;
103pub mod kernel;
104pub mod kernel_api;
105pub mod kernel_runner;
106pub mod metadata;
107pub mod packet;
108pub mod runtime;
109pub mod status;
110pub mod timestamp;
111pub mod trace;
112
113pub use graph::{
114 DotView, Graph, Input, OutputEvent, Poller, PollerBackpressureStatsSnapshot, PollerOptions,
115 PollerOverflow, State, WatermarkBackpressureStatsSnapshot,
116};
117pub use kernel_api::{register_kernel, Kernel, KernelContract, KernelCtx};
118pub use kernel_runner::KernelRunner;
119pub use metadata::{Metadata, MetadataPredicate, MetadataValue};
120pub use packet::{BufferData, Builtin, InteropType, Packet};
121pub use status::{Error, Result};
122pub use timestamp::Timestamp;