繁体   English   中英

Rust 2021 与 2018:特征 `std::marker::Send` 未实现 - 在 2021 版中执行此操作的正确方法是什么?

[英]Rust 2021 vs. 2018: trait `std::marker::Send` is not implemented - what is the correct way to do this in 2021 edition?

我目前正在学习关于 Rust 的课程,并发现有一些内容可以与 2018 版的 Rust 而不是 2021 版一起编译。 虽然我可以更改我的版本并继续,但我想进一步了解如果我使用的是 2021 版本,正确的操作方法是什么,以及为什么会出现差异?

2021版附带的错误是:

let handle = std::thread::spawn(move || {
             ^^^^^^^^^^^^^^^^^^
             *mut [T] cannot be sent between threads safely
    threaded_fun(&mut *raw_s.0)
});
=help: ... the trait `Send` is not implemented for `*mut [T]`

原始代码正在处理多线程排序功能,但我试图尽可能多地取出,以便它只是拆分一个向量并打印它的进度。

use std::fmt::Debug;

struct RawSend<T>(*mut [T]); // one element tuple

unsafe impl<T> Send for RawSend<T> {}

pub fn threaded_fun<T: 'static + PartialOrd + Debug + Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }
    let p = v.len()/2;
    println!("{:?}", v);

    let (a, b) = v.split_at_mut(p);

    let raw_a: *mut [T] = a as *mut [T];
    let raw_s = RawSend(raw_a);

    unsafe {
        let handle = std::thread::spawn(move || {
            threaded_fun(&mut *raw_s.0)
        });
        threaded_fun(&mut b[..]);

        // unsafe is required because compiler doesn't know we combine these
        handle.join().ok();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn threaded_test() {
        let mut v = vec![1,2,3,4,5,6,7,8,9,10];
        threaded_fun(&mut v);
        panic!(); // Test is just to activate the function. `cargo test`
    }
}

这是因为2021 版在闭包中有部分捕获

这意味着在 Rust 2018 中,

|| a.b

将完整捕获“a”,但在 Rust 2021 中,它将仅执行部分捕获ab ,并且如果结构具有其他字段,则这些字段仍可供闭包的创建者使用。

但是,在您的情况下,这意味着raw_s.0是捕获并用于计算闭包特征的内容,并且由于它不是Send (因为它是原始指针),因此闭包也不再是Send 在版本变更日志中特别指出了特征计算的变化。

您可以通过强制捕获结构本身来解决此问题,例如

let raw_s = raw_s;

或者

let _ = &raw_s;

请注意,cargo 有一个cargo fix子命令,可以为您迁移此类更改(使用--edition标志)。

这是因为 2021 版改变了闭包的捕获方式。 在 2018 年,他们捕获整个结构,但在 2021 年,他们将捕获单个结构成员。

这会导致闭包尝试捕获原始指针( raw_s.0 )而不是整个RawSend 您可以通过显式强制raw_s移动来解决此问题:

    unsafe {
        let handle = std::thread::spawn(move || {
            let raw_s = raw_s;
            threaded_fun(&mut *raw_s.0)
        });
        threaded_fun(&mut b[..]);

        // unsafe is required because compiler doesn't know we combine these
        handle.join().ok();
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM