9 个稳定版本
1.3.0 | 2020年2月17日 |
---|---|
1.2.2 | 2018年2月25日 |
1.2.1 | 2017年8月18日 |
1.2.0 | 2017年5月10日 |
1.0.1 | 2016年7月12日 |
#373 in 操作系统
用于 weechat
18KB
261 行
pipe-channel
Rust 编程语言的基于管道的通道实现
lib.rs
:
基于管道的通道实现。
这个crate提供了一个与 std::sync::mpsc
API 类似的通道实现,基于操作系统级别的管道。管道由底层的操作系统内核进行缓冲。
Sender 和 Receiver 结构体都实现了 AsRawFd
、FromRawFd
和 IntoRawFd
特性,使得它们可以与 select()
系统调用一起使用,或者在需要文件描述符的其他地方。这允许通道轻松集成到各种事件循环中。
示例
use std::thread;
use pipe_channel::*;
let (mut tx, mut rx) = channel();
let handle = thread::spawn(move || {
tx.send(35).unwrap();
tx.send(42).unwrap();
});
assert_eq!(rx.recv().unwrap(), 35);
assert_eq!(rx.recv().unwrap(), 42);
handle.join().unwrap();
所有权
与 std::sync::mpsc
通道不同,Sender::send()
和 Receiver::recv()
都接受 &mut self
。因此,无法共享或克隆 Sender
。请使用常规的 Arc<Mutex<Sender<T>>>
代替
use std::thread;
use std::sync::{Arc, Mutex};
use pipe_channel::*;
// Create a shared channel that can be sent along from many threads
// where tx is the sending half (tx for transmission), and rx is the receiving
// half (rx for receiving).
let (tx, mut rx) = channel();
let tx = Arc::new(Mutex::new(tx));
for i in 0..10 {
let tx = tx.clone();
thread::spawn(move|| {
let mut tx = tx.lock().unwrap();
tx.send(i).unwrap();
});
}
for _ in 0..10 {
let j = rx.recv().unwrap();
assert!(0 <= j && j < 10);
}
多线程和多进程
在较低级别,完全支持从一个进程到另一个进程的管道。这意味着在执行fork()
之后,可以使用通道在进程之间发送数据。然而,请注意,所涉及的数据可能包括一些进程本地数据,如引用、指针、文件描述符等。因此,这样使用通道并不安全。
与SIGPIPE的关系
当读取端关闭时,在管道上调用write()
会将SIGPIPE信号发送给进程。这意味着当相应的Receiver
被丢弃时,会向进程发送SIGPIPE。
在Rust可执行程序中,SIGPIPE默认被忽略。但请确保在您的情况下也是如此。Sender::send()
只有在底层系统调用返回EPIPE
时才会返回Err
。有关更多详细信息,请参阅手册页。
性能
与针对最高性能调整过的std::sync::mpsc
通道不同,这个实现完全依赖于内核。简单来说,它所做的就是在管道中按字节复制对象。对于正常大小的对象来说,这应该足够快。如果您需要发送一个巨大的对象,考虑将其包装到一个Box
中,并发送那个。
操作系统兼容性
这应该适用于任何类UNIX操作系统。
恐慌
系统调用的Result
被unwrap
处理(除了EPIPE)。因此,如果其中任何一个失败,程序将引发恐慌。虽然这种情况很少见,但并非完全意外(例如,程序可能会耗尽文件描述符)。
依赖关系
~1.5MB
~36K SLoC