Rust 是否可以在没有互斥的情况下从Fn调用Fn一次?
Rust 是否可以在没有互斥的情况下从Fn调用Fn一次?,rust,Rust,Fn可以通过通道发送,但是FnOnce还不能在稳定状态下发送。为了通过通道发送一次Fn,可以将其包装在Fn中,如下所示 但是,这需要一个互斥对象,当扩展到非常高的吞吐量时,这会带来恼人的开销(也就是说,当您经常这样做时,它的速度很慢) 是否有其他一些并发原语我可以在这里使用,这将是较轻的重量?可能使用std::sync::atomic?这可以不用锁吗 我对使用依赖于未定义行为的夜间功能或板条箱不感兴趣 use std::thread; use std::sync::Mutex; use std:
Fn
可以通过通道发送,但是FnOnce
还不能在稳定状态下发送。为了通过通道发送一次Fn
,可以将其包装在Fn
中,如下所示
但是,这需要一个互斥对象
,当扩展到非常高的吞吐量时,这会带来恼人的开销(也就是说,当您经常这样做时,它的速度很慢)
是否有其他一些并发原语我可以在这里使用,这将是较轻的重量?可能使用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();
}
使用std::thread;
使用std::sync::Mutex;
使用std::sync::mpsc;
结构RawFunc{
数据:框(i.take().unwrap())(),
Err()=>{}
}),
};
}
fn调用(自我){
(自我数据)()
}
}
fn main(){
//本地的
设x=RawFunc::new(move | |){
println!(“你好世界”);
});
x、 调用();
//通过渠道
let(sx,rx)=mpsc::channel::();
发送(RawFunc::新建(移动| |){
println!(“你好,世界2”);
})).unwrap();
让输出=rx.recv().unwrap();
output.invoke();
//一线生机
让守卫=线程::繁殖(移动| |{
让输出=rx.recv().unwrap();
output.invoke();
});
发送(RawFunc::新建(移动| |){
println!(“你好,世界3!”);
})).unwrap();
防护罩。连接()。展开();
//向线程传递任意数据
let(sx,rx)=mpsc::channel::();
让守卫=线程::繁殖(移动| |{
让输出=rx.recv().unwrap();
output.invoke();
});
让bar=RawFunc::new(移动| |){
println!(“Moved func!”);
});
让foo=String::from(“Hello World 4”);
发送(RawFunc::新建(移动| |){
println!(“某些移动数据:{:?}”,foo);
bar.invoke();
})).unwrap();
防护罩。连接()。展开();
}
这本书的作者有着完全相同的问题,并以他们自己的特点解决了这个问题
/// 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)
}
}
///异步回调函数特性。
///
///每个`FnOnce(&mut草书)->()+Send`自动
///实现这一点。
///
///这是一种变通方法,因为“Box”不是
///正在工作,“FnBox”不稳定。
发布功能:发送{
///调用函数。
fn调用框(self:box和mut草书);
}
函数的impl()+Send>CbFunc{
fn调用框(self:box、siv:&mut草书){
(*自我)(siv)
}
}
,这里介绍了代码。也许这可以帮助您:@hellow,太好了,谢谢!你想把它作为一个答案吗?我很乐意接受。似乎效果很好,例如,为什么使用
Fn
而不是FnMut
?您只需要Send
而不需要Sync
,这样就可以用RefCell
替换Mutex
。