链接到操场(或者下面也是代码):https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d6a8e4e6b9fa6aa647b2651e58402aa0
我想从库中为代码编写一个测试。main方法外部的代码具有与库(https://github.com/housleyjk/ws-rs/blob/master/src/lib.rs#L110)相同的结构。
在某种程度上,我希望提供一个可以在线程中随时间变化的值。稍后,我必须在另一个线程中断言该值。硬部分是,包含更改值的类型的实例化是在FnMut闭包中构造的。
我试着移动它,我尝试了RefCell,我尝试了Arc,但是我不幸地失败了。有什么建议吗?
use std::thread::sleep;
use std::time::Duration;
trait Fly {}
trait Surf {
fn will_be_called_after_two_seconds(&mut self);
}
struct Roll;
struct FlyingBird;
impl Fly for FlyingBird {}
struct SurfingDog(bool);
impl Surf for SurfingDog {
fn will_be_called_after_two_seconds(&mut self) {
self.0 = true;
}
}
fn closure_boi<F, S>(x: F) where F: FnMut(Roll) -> S, S: Surf {}
fn main() {
let val = false;
std::thread::spawn(|| {
closure_boi(|_| {
SurfingDog(val)
});
});
sleep(Duration::from_secs(5));
assert_eq!(true, val);
}发布于 2019-12-30 21:46:21
有几个问题可以阻止上述代码的工作:
main中的一个勺),那么铁锈将不允许您在两个线程之间共享一个值。修复方法是要么堆分配值,然后使用Arc跟踪它,要么使用crossbeam_utils::thread::scope创建线程,这确实提供了这样的保证。由于您可能需要生成的线程来保持并行运行,所以让我们来看看Arc。SurfingDog不能只包含布尔值,它必须包含对布尔值的引用,或者整个SurfingDog实例必须在main中可用。在当前代码中,由其他线程修改的布尔值驻留在从它接收的闭包中获得的SurfingDog值closure_boi中,这是与在main中签入的val不同的值。Mutex这样的锁,要么使用像AtomicBool这样的原子类型。考虑到上述情况,下面是对编译和工作代码(游乐场)的修改:
use std::sync::{Arc, Mutex};
use std::thread::sleep;
use std::time::Duration;
trait Surf {
fn will_be_called_after_two_seconds(&mut self);
}
struct SurfingDog<'a>(&'a Mutex<bool>);
impl<'a> Surf for SurfingDog<'a> {
fn will_be_called_after_two_seconds(&mut self) {
let mut state = self.0.lock().unwrap();
*state = true;
}
}
fn closure_boi<S: Surf>(mut x: impl FnMut() -> S) {
let mut surfer = x();
sleep(Duration::from_secs(2));
surfer.will_be_called_after_two_seconds();
sleep(Duration::from_secs(10)); // keep running
}
fn main() {
let val = Arc::new(Mutex::new(false));
std::thread::spawn({
let val = Arc::clone(&val);
move || {
closure_boi(|| SurfingDog(&*val));
}
});
sleep(Duration::from_secs(5));
assert_eq!(true, *val.lock().unwrap());
}https://stackoverflow.com/questions/59536752
复制相似问题