gpt4 book ai didi

rust - 是否可以在没有 Mutex 的情况下从 Fn 调用 FnOnce?

转载 作者:行者123 更新时间:2023-11-29 08:06:04 25 4
gpt4 key购买 nike

Fn 可以通过 channel 发送,但是 FnOnce 还不能稳定。为了通过 channel 发送 FnOnce,可以将其包装在 Fn 中,如下所示。

但是,这需要一个 Mutex,这会在扩展到非常高的吞吐量时引入恼人的开销(即,明显地,当你经常这样做时,它会很慢)。

我可以在这里使用其他一些不那么重量级的并发原语吗?也许使用 std::sync::atomic?这可以在没有锁的情况下完成吗?

我对使用依赖于未定义行为的夜间功能或 crate 没有兴趣。

use std::thread;
use std::sync::Mutex;
use std::sync::mpsc;

struct RawFunc {
data: Box<Fn() + Send + 'static>,
}

impl RawFunc {
fn new<T>(inner: T) -> RawFunc
where
T: FnOnce() + Send + 'static,
{
let inner_lock = Mutex::new(Some(inner));
return RawFunc {
data: Box::new(move || match inner_lock.lock() {
Ok(mut i) => (i.take().unwrap())(),
Err(_) => {}
}),
};
}

fn invoke(self) {
(self.data)()
}
}

fn main() {
// Local
let x = RawFunc::new(move || {
println!("Hello world");
});
x.invoke();

// Via channel
let (sx, rx) = mpsc::channel::<RawFunc>();
sx.send(RawFunc::new(move || {
println!("Hello world 2");
})).unwrap();
let output = rx.recv().unwrap();
output.invoke();

// In a thread
let guard = thread::spawn(move || {
let output = rx.recv().unwrap();
output.invoke();
});

sx.send(RawFunc::new(move || {
println!("Hello world 3!");
})).unwrap();

guard.join().unwrap();

// Passing arbitrary data to a thread
let (sx, rx) = mpsc::channel::<RawFunc>();
let guard = thread::spawn(move || {
let output = rx.recv().unwrap();
output.invoke();
});

let bar = RawFunc::new(move || {
println!("Moved func!");
});
let foo = String::from("Hello World 4");
sx.send(RawFunc::new(move || {
println!("Some moved data: {:?}", foo);
bar.invoke();
})).unwrap();

guard.join().unwrap();
}

playground

最佳答案

cursive crate 的作者有完全相同的问题,并用自己的特点解决了它。

/// Asynchronous callback function trait.
///
/// Every `FnOnce(&mut Cursive) -> () + Send` automatically
/// implements this.
///
/// This is a workaround only because `Box<FnOnce()>` is not
/// working and `FnBox` is unstable.
pub trait CbFunc: Send {
/// Calls the function.
fn call_box(self: Box<Self>, &mut Cursive);
}

impl<F: FnOnce(&mut Cursive) -> () + Send> CbFunc for F {
fn call_box(self: Box<Self>, siv: &mut Cursive) {
(*self)(siv)
}
}

source

Here is the PR , 引入代码的地方。

关于rust - 是否可以在没有 Mutex 的情况下从 Fn 调用 FnOnce?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49142453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com