关于并发:替代克隆tokio频道的发件人以进行期货平仓

Alternative to cloning tokio channel's sender for futures' closures

我正在使用tokiohyper来产生多个任务。

1
2
3
4
5
6
7
// Defining the task
let task = self.some_future_using
            .map(move |resp| println!("OK: {}", resp))
            .map_err(move |e| println!("Error: {}",e));

// Spawning the task
tokio::spawn(task);

我想通过有限的tokio通道发送结果,而不是简单地记录结果。

1
2
3
4
5
6
7
8
9
10
// Defines the channel
let (tx, rx) = mpsc::channel(10);

// Defining the task
let task = self.some_future_using
            .map(|resp| /* Send Ok(resp) to tx */ )
            .map_err(|e| /* Send Err(e) to tx */);

// Spawning the task
tokio::spawn(task);

由于两个闭包都可能超出定义tx的范围,因此我们需要克隆并移动两个闭包的tx

1
2
3
4
5
6
7
8
9
10
11
12
// Defines the channel
let (tx, rx) = mpsc::channel(10);
let mut tx_ok = tx.clone();
let mut tx_err = tx.clone();

// Defining the task
let task = self.some_future_using
            .map(move |resp| tx_ok.try_send(Ok(())).unwrap() )
            .map_err(move |e| tx_err.try_send(Ok(())).unwrap() );

// Spawning the task
tokio::spawn(task);

在使用组合器(mapand_then等)添加更多逻辑的情况下,每个闭包都需要它自己的tx克隆版本才能使用它。

克隆是唯一的解决方案吗?我们能否在不为使用该声明的每个闭包克隆通道发送者的情况下实现相同的目的?


Could we achieve the same without cloning the channel's sender for each declared closure that uses it?

不。这是共享Sender的方式,并且没有另一种安全的方式来实现它。

通道通过将共享资源package在Arc中来管理共享资源,因此可以在线程之间安全地共享它们。 Sender \\的clone方法涉及一些逻辑,但是最终它是关于克隆那些Arc s的-这就是共享Arc s的方式。

克隆Arc很便宜,除非您将它们克隆成一个紧密的循环,否则不必担心。克隆后,Arc的开销很小-每个克隆本质上都是一个指针。