8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Rust 2021 与 2018:特征“std::marker::Send”未实现——在 2021 版中正确的执行方法是什么?

Bahae El Hmimdi 2月前

36 0

我目前正在学习一门有关 Rust 的课程,发现有些内容可以与 2018 版 Rust 编译,但不能与 2021 版编译。虽然我可以更改我的版本并继续...

我目前正在学习 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`
    }
}
帖子版权声明 1、本帖标题:Rust 2021 与 2018:特征“std::marker::Send”未实现——在 2021 版中正确的执行方法是什么?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Bahae El Hmimdi在本站《multithreading》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 这是因为 2021 版在闭包中有部分捕获 .

    这意味着在 Rust 2018 中,

    || a.b
    

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

    但是,在您的情况下,它的意思 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();
        }
    
返回
作者最近主题: