Fn
可以通过渠道发送,但FnOnce
尚未稳定。要通过渠道发送FnOnce
,可以将其打包在Fn
中,如下所示。
但是,这需要一个Mutex
,这会在扩展到非常高的吞吐量时引入恼人的开销(即,实际上,当你这么做时,它很慢)。
我是否可以使用其他一些不太重量级的并发原语?或许std::sync::atomic
?这可以在没有锁定的情况下完成吗?
我没有兴趣使用依赖于未定义行为的夜间特征或板条箱。
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();
}
答案 0 :(得分:3)
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)
}
}
Here is the PR,代码介绍。