Appliance
Overview
Appliance is a lightweight Rust framework for building highly customizable asynchronous components adapted for message-based intercommunications. This project is an attempt to make actix-like approach more flexible by exempting a user from using predefined execution runtimes. With the library you can design any composition logic for async agents avoiding data races and unnecessary locks.
Features
- Explicit control over agent lifecycle (no global runtime).
- Equipping agents with customized async executors.
- Minimal overhead when calling handlers (no traits used).
- Use of stack for small messages.
Installation
The recommended way to use this library is to add it as a dependency in your Cargo.toml
file:
[dependencies]
appliance = "0.1.4"
A quick ping-pong example
use appliance::Appliance;
use std::{
sync::{Arc, Weak},
thread,
time::Duration,
};
enum PingMessage {
RegisterPong(Weak<Appliance>),
Send(i16),
}
#[derive(Default)]
struct PingState {
pong: Weak<Appliance>,
}
fn ping_handler(state: &mut PingState, message: PingMessage) {
match message {
PingMessage::RegisterPong(pong) => state.pong = pong,
PingMessage::Send(c) => {
if let Some(pong) = &state.pong.upgrade() {
println!("ping received {}", c);
let _ = pong.handle(PongMessage::Send(c + 1));
thread::sleep(Duration::from_secs(1));
}
}
}
}
enum PongMessage {
RegisterPing(Weak<Appliance>),
Send(i16),
}
#[derive(Default)]
struct PongState {
ping: Weak<Appliance>,
}
fn pong_handler(state: &mut PongState, message: PongMessage) {
match message {
PongMessage::RegisterPing(ping) => state.ping = ping,
PongMessage::Send(c) => {
if let Some(ping) = &state.ping.upgrade() {
println!("pong received {}", c);
let _ = ping.handle(PingMessage::Send(c + 1));
thread::sleep(Duration::from_secs(1));
}
}
}
}
fn main() {
let executor = &appliance::DEFAULT_EXECUTOR;
let ping_state: PingState = Default::default();
let ping = Arc::new(Appliance::new_unbounded(executor, ping_state, ping_handler));
let pong_state: PongState = Default::default();
let pong = Arc::new(Appliance::new_unbounded(executor, pong_state, pong_handler));
let _ = ping.handle(PingMessage::RegisterPong(Arc::downgrade(&pong)));
let _ = pong.handle(PongMessage::RegisterPing(Arc::downgrade(&ping)));
let _ = ping.handle(PingMessage::Send(0));
thread::sleep(Duration::from_secs(5));
}