#message #queue #subscriber #typed #mechanism #dispatcher #greeting

bottles

无枚举类型的类型化消息传递机制

2 个版本

0.1.1 2020年3月24日
0.1.0 2020年3月24日

#8 in #greeting

MIT 许可证

16KB
220

Bottles

Bottles 是一个 Rust 库,用于进行强类型消息传递,不使用枚举类型。这种方法的优点是添加新的消息类型非常容易,每个类型的尺寸不是所有类型中最大的(就像枚举类型那样)。

状态

这是一个非常早期的作品。


lib.rs:

bottles

无枚举类型的类型化消息传递机制

这个 crate 允许将任何 'static 类型的消息放入瓶子中,然后可以将这些消息分发给该类型的订阅者。

这个 crate 中有两个主要类型:[Dispatcher](https://docs.rs/bottles/0.1.1/dispatcher/struct.Dispatcher.html) 和 [Queue](https://docs.rs/bottles/0.1.1/queue/struct.Queue.html)

Dispatcher

一个简单的类型与接收该类型消息的订阅者列表之间的映射。订阅者是一个闭包,它接受一个类型为 Rc<T> 的单个参数,每当分发具有该类型的消息时,它将被调用。

通常很难对没有任何 上下文 的消息做出反应,人们必须依赖于在闭包中捕获 Rc<RefCell<Context>> 以修改外部世界。提供的最简单的解决方案是使用 Queue 作为 Dispatcher 和回调本身之间的中间组件。

Queue

Queue 允许从一个或多个分发器收集消息,并在调用 Queue.poll 方法时将它们内部排队,该方法 允许 为所有订阅者提供“上下文”值。

Queue 订阅者是一个闭包,它恰好接受两个参数:对上下文字符变量的 &mut 引用和一个类型为 Rc<T> 的消息。

示例

向订阅者发送问候

use std::rc::Rc;
use bottles::Dispatcher;

struct Greeting {
    greeting: String
}

fn callback(msg: Rc<Greeting>) {
    println!("Greeting: {}", msg.greeting);
}

    let mut dispatcher = Dispatcher::new();

    // Every message type has to be registered explicitly
    // It is a design choice to have a error when subscribing for a message type which is
    // not registered by the particular Dispatcher, to error out as quickly as possible
    dispatcher.register::<Greeting>();

    dispatcher.subscribe(callback);

    dispatcher.dispatch(Rc::new(Greeting { greeting: "Hello there!".to_string() }));

创建一个具有可变上下文的回调

use std::rc::Rc;
use bottles::{Dispatcher, Queue};

struct Add(i32);

struct Context {
    state: i32
}

fn add(ctx: &mut Context, msg: Rc<Add>) {
    ctx.state += msg.0;
}

let mut dispatcher = Dispatcher::new();
let mut queue = Queue::new();

queue.register::<Add>(&mut dispatcher);

queue.subscribe(&mut dispatcher, add);

// `queue` will receive the message and enqueue it for retrieval when polled.
dispatcher.dispatch(Rc::new(Add(42)));

let mut context = Context {
    state: 0
};

// Very important: Queue has works by being polled, because this allows to pass a reference
// to the context without resorting to any interior mutability patterns.
queue.poll(&mut context);

assert_eq!(context.state, 42);

无运行时依赖