简体   繁体   中英

Is it safe to modify an Arc<Mutex<T>> from both a Rust thread and a foreign thread?

Are there any general rules, design documentation or something similar that explains how the Rust standard library deals with threads that were not spawned by std::thread ?

I have a cdylib crate and want to use it from another language in a threaded manner:

use std::mem;
use std::sync::{Arc, Mutex};
use std::thread;

type jlong = usize;
type SharedData = Arc<Mutex<u32>>;

struct Foo {
    data: SharedData,
}

#[no_mangle]
pub fn Java_com_example_Foo_init(shared_data: &SharedData) -> jlong {
    let this = Box::into_raw(Box::new(Foo { data: shared_data.clone() }));
    this as jlong
}

#[cfg(target_pointer_width = "32")]
unsafe fn jlong_to_pointer<T>(val: jlong) -> *mut T {
    mem::transmute::<u32, *mut T>(val as u32)
}

#[cfg(target_pointer_width = "64")]
unsafe fn jlong_to_pointer<T>(val: jlong) -> *mut T {
    mem::transmute::<jlong, *mut T>(val)
}

#[no_mangle]
pub fn Java_com_example_Foo_f(this: jlong) {
    let mut this = unsafe { jlong_to_pointer::<Foo>(this).as_mut().unwrap() };
    let data = this.data.clone();
    let mut data = data.lock().unwrap();
    *data = *data + 5;
}

specifically in

let shared_data = Arc::new(Mutex::new(5));
let foo = Java_com_example_Foo_init(&shared_data);

is it safe to modify shared_data from a thread spawned by thread::spawn if Java_com_example_Foo_f will be called from an unknown JVM thread?

Possible reason why it can be bad.

Yes. The issue you linked relates to librustrt , which was removed before Rust 1.0. RFC 230 , which removed librustrt , specifically notes:

When embedding Rust code into other contexts -- whether calling from C code or embedding in high-level languages -- there is a fair amount of setup needed to provide the "runtime" infrastructure that libstd relies on. If libstd was instead bound to the native threading and I/O system, the embedding setup would be much simpler.

Additionally, see PR #19654 which implemented that RFC:

When using Rust in an embedded context, it should now be possible to call a Rust function directly as a C function with absolutely no setup, though in that case panics will cause the process to abort. In this regard, the C/Rust interface will look much like the C/C++ interface.

For current documentation, the Rustonomicon chapter on FFI 's examples of Rust code to be called from C make use of libstd (including Mutex , I believe, though that's an implementation detail of println ) without any caveats relating to runtime setup.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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