更改其他线程中的值并断言后一个(在“主”线程中)

时间:2019-12-30 20:56:06

标签: rust

链接到游乐场(或以下也是代码):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);
}

1 个答案:

答案 0 :(得分:0)

有几个问题可能会导致上述代码无法正常工作:

  • 如果不能证明使用它的线程不会超过该值本身,Rust将不允许您在两个线程之间共享一个值(在这种情况下,main中是一个场景)。解决方法是要么堆分配值并使用Arc来跟踪它,要么使用crossbeam_utils::thread::scope创建线程,这确实提供了保证。由于您可能需要生成的线程来保持并行运行,因此我们来研究Arc
  • SurfingDog不能仅包含布尔值,它必须包含对布尔值的引用,或者整个SurfingDog实例必须在{{1}中可用}。在当前代码中,由另一个线程修改的布尔值驻留在mainSurfingDog中,该值是从它收到的闭包中获得的,该值与{{1 }}。
  • Rust不允许其他线程修改第一个线程在不同步的情况下读取的值,因为这将构成data race。解决方法是使用Mutex之类的锁,或者使用AtomicBool之类的原子类型。

考虑到上述情况,这是对编译和运行的代码的修改(playground):

closure_boi