I'm using the object from a crate, which was not written by me and i have a struct which i would like to use as a global variable, but i get this error:
error[E0277]: `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely
--> src\main.rs:76:37
|
76 | fn init_emulator(emulator_instance: State<EmulatorGlobal>) {
| ^^^^^^^^^^^^^^^^^^^^^ `Rc<UnsafeCell<UnicornInner<'static, ()>>>` cannot be sent between threads safely
|
= help: within `Unicorn<'static, ()>`, the trait `Send` is not implemented for `Rc<UnsafeCell<UnicornInner<'static, ()>>>`
= note: required because it appears within the type `Unicorn<'static, ()>`
= note: required for `std::sync::Mutex<Unicorn<'static, ()>>` to implement `Send`
note: required because it appears within the type `EmulatorGlobal`
--> src\main.rs:27:8
|
27 | struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>);
| ^^^^^^^^^^^^^^
note: required by a bound in `State`
--> C:\Users\Aslan\.cargo\registry\src\github.com-1ecc6299db9ec823\tauri-1.2.2\src\state.rs:14:25
|
14 | pub struct State<'r, T: Send Sync 'static>(&'r T);
| ^^^^ required by this bound in `State`
My guess is that the problem occurs due to usage of "UnsafeCell". I wounder if there is a proper and easy way to "monkeypatch" this code and keep the whole project safe. Below is the code of the struct:
/// A Unicorn emulator instance.
pub struct Unicorn<'a, D: 'a> {
inner: Rc<UnsafeCell<UnicornInner<'a, D>>>,
}
Any help appreciated.
I am writing an app with tauri, so i defined the variable as follows:
struct EmulatorGlobal(Mutex<Unicorn<'static, ()>>);
Here is it's usage in the code
#[tauri::command]
fn init_emulator(emulator_instance: State<EmulatorGlobal>) {
let mut unicorn: Unicorn<()> = Unicorn::new(Arch::X86, Mode::MODE_64).expect("ERROR");
}
Upd: The struct uses not the std::rc::Rc, but alloc::rc::Rc (Not sure if they are different, but according to the documentation, they seem similar). (Thanks to @erikkallen for reminding)
CodePudding user response:
The core of your question is how to store a unicorn_engine::Unicorn
in a static
variable (or used for a type constrained to be Send
based on your error) and the answer is you cannot.
As the error leaks, it internally uses an Rc
which is not thread-safe. Any attempts to "monkeypatch" it into working would be unsound.
A workaround to make use of a non-thread-safe type in a multi-threaded system would be to create a single thread to hold and operate on that object and use channels to communicate actions and/or results to the rest of the system. Though considering this type in particular, it could be very tedious depending on what you are doing.
CodePudding user response:
I'm not a Rust expert, but I'm pretty sure you need an Arc instead of an Rc if you send it between threads.