#channel #map #mpsc #iterator

transformable_channels

Rust 通道是一种便捷的抽象,但对于许多用例,它们缺少高级转换,如 mapfilter 等。这个软件包引入了这些转换。

2 个版本

使用旧的 Rust 2015

0.1.1 2016 年 3 月 13 日
0.1.0 2016 年 3 月 13 日

2272Rust 模式

MPL-2.0 许可证

20KB
312 行

Build Status

文档

当前问题

考虑一个事件循环,定义如下

let (tx, rx) = channel();
thread::spawn(move || {
  for event in rx {
    match event {
      UIEvent::KeyboardEvent(ev) => { ... },
      UIEvent::MouseEvent(ev) => { ... },
      ...
    }
  }
});

现在,想象一个可以监听键盘事件的系统库,具有以下签名

impl ThirdPartyLibrary {
  fn register_watch(&self, on_event: Sender<PrimitiveKeyboardEvent>) -> ...;
}

我们如何与这个库交互?嗯,使用 Sender,唯一的办法是启动另一个线程,如下所示

let (tx2, rx2) = channel();
let tx = tx.clone(); // That's the tx for my event loop, see above.
thread::spawn(move || {
  for ev in rx {
    match tx.send(UIEvent::KeyboardEvent(ev) {
      Ok(_) => {},
      Err(_) => return, // Cleanup if nobody is listening anymore.
    }
  }
});

third_party_library.register_watch(tx2);

如果我们可以编写以下内容并使其在没有启动线程的情况下工作,那不是更好且更节省资源吗?

third_party_library.register_watch(tx.map(|ev| UIEvent::KeyboardEvent(ev)));

现在,让我们假设情况稍微复杂一些,并且我们的系统需要处理多个键盘。现在,我们需要给每个键盘分配一个唯一的键。

使用 Sender,唯一的解决方案是为每个键盘启动 一个线程,即

let key = ...;
let (tx3, rx3) = channel();
let tx = tx.clone(); // That's the tx for my event loop, see above.
thread::spawn(move || {
  for ev in rx {
    match tx.send(UIEvent::KeyboardEvent(key, ev) {
      Ok(_) => {},
      Err(_) => return, // Cleanup if nobody is listening anymore.
    }
  }
});

third_party_library.register_watch(tx3);

如果我们可以编写以下内容并使其在没有启动线程的情况下工作,那不是更好且更节省资源吗?

let key = ...;
third_party_library.register_watch(tx.map(move |ev| UIEvent::KeyboardEvent(key, ev)));

这个软件包旨在实现更优雅且更节省资源的策略。

没有运行时依赖项