为什么我不能在线程之间发送 Mutex<*mut c_void>?

Nul*_*lik 5 rust

我需要在 Rust 线​​程之间共享从 C++ 创建的对象。我已经将它包装在一个Mutex结构中,所以现在在线程之间发送是安全的。但是编译器不会让我做什么。

error[E0277]: `*mut std::ffi::c_void` cannot be sent between threads safely
   --> sendsync.rs:14:2
    |
14  |     thread::spawn(move || {
    |     ^^^^^^^^^^^^^ `*mut std::ffi::c_void` cannot be sent between threads safely
    |
    = help: within `Api`, the trait `std::marker::Send` is not implemented for `*mut std::ffi::c_void`
    = note: required because it appears within the type `OpaqWrapper`
    = note: required because it appears within the type `Api`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<Api>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<std::sync::Mutex<Api>>`
    = note: required because it appears within the type `[closure@sendsync.rs:14:16: 19:3 safe_obj:std::sync::Arc<std::sync::Mutex<Api>>]`
Run Code Online (Sandbox Code Playgroud)

我应该如何根据 Rust 规则实现这一点?这是代码:

use std::{
    sync::{
        Arc,Mutex,
    },
    ptr,
    thread::{self},
};
pub struct OpaqWrapper {
    pub obj_ptr: *mut ::std::os::raw::c_void,
}
pub struct Api(OpaqWrapper);

fn spawn_api_thread(safe_obj: Arc<Mutex<Api>>) {
    thread::spawn(move || {
        {
            let my_api = safe_obj.lock().unwrap();
            // my_api.whatever();
        }
    });
}

fn main() {
    let api = Api(
        OpaqWrapper {
            obj_ptr: ptr::null_mut(),
        }
    );
    let shared_api= Arc::new(Mutex::new(api));
    for _ in 0..10 {
        spawn_api_thread(shared_api.clone());
    }
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*son 7

精简版

将某些东西传递给线程需要它是Send.

T:Send => Mutex<T>:Send+Sync =>  Arc<Mutex<T>>:Send
Run Code Online (Sandbox Code Playgroud)

所以标记ApiSend

长版

将某些东西传递给线程需要它是Send.

Arc<T>仅在是and 时自动获取Send(和Sync)。源包含如下内容:TSendSync

unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {}
Run Code Online (Sandbox Code Playgroud)

但是,Mutex只要求Send它是Syncand Send,它的代码包含:

unsafe impl<T: ?Sized + Send> Send for Mutex<T> { }
unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
Run Code Online (Sandbox Code Playgroud)

这意味着Arc<Mutex<Api>>要成为Sync,你需要Mutex<Api>成为 Sync+Send,如果Api是,就会发生Send。要获得此信息,您需要将Api或标记OpaqWrapperSend

unsafe impl Send for Api {}
Run Code Online (Sandbox Code Playgroud)

注意你不需要它们标记为SyncMutex自动获取。