Share *mut T between threads wrapped in Mutex

Hi Rustaceans,

I’m new to Rust. As my first project I’m reimplementing a multi-threaded programm with a central RDF-graph as knowledge base.
For working with RDF I wrote some Rust-bindings for the Redland API. I wrapped the pointers I get from C in Rust-structs.

To communicate with the RDF-data in multiple threads I wrote some Management-struct. The problem I’m now facing is that my wrapper-structs contain *mut ptr causing the wrappers not to implement neither Send or Sync. I thought that if I wrap my Manager in an Arc<Mutex<>> sending to multiple threads wouldn’t be a problem because the Mutex ensures mutual exclusion therefore making the unsafe *mut ptr threadsafe.

Have you experienced Rustaceans some advices how I could fix this issue?

That’s one of my compiler errors:

error[E0277]: `*mut librdf_rs::extern_c::world::CLibrdfWorld` cannot be shared between threads safely
  --> src/adapter/mod.rs:30:13
   |
30 |             thread::spawn(|| {
   |             ^^^^^^^^^^^^^ `*mut librdf_rs::extern_c::world::CLibrdfWorld` cannot be shared between threads safely
   |
   = help: within `semantic_management::RdfFactory`, the trait `std::marker::Sync` is not implemented for `*mut librdf_rs::extern_c::world::CLibrdfWorld`
   = note: required because it appears within the type `librdf_rs::World`
   = note: required because it appears within the type `semantic_management::RdfFactory`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<semantic_management::RdfFactory>`
   = note: required because it appears within the type `adapter::semantics::SemanticAnnotator`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Mutex<adapter::semantics::SemanticAnnotator>`
   = note: required because of the requirements on the impl of `std::marker::Sync` for `std::sync::Arc<std::sync::Mutex<adapter::semantics::SemanticAnnotator>>`
   = note: required because it appears within the type `adapter::Adapter`
   = note: required because it appears within the type `&adapter::Adapter`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&&adapter::Adapter`
   = note: required because it appears within the type `[closure@src/adapter/mod.rs:30:27: 35:14 self:&&adapter::Adapter]`
   = note: required by `std::thread::spawn`

Assuming the structure wraps safely;
unsafe impl Send for Management{}

Thank you for your quick answer @jonh.

I read about the solution implementing Send (and Sync) manually. My hope was to find some more Rust idiomic way for this problem avoiding unsafe. But I think I have to live with unsafe since I use C bindings and raw pointers.

By the way does anyone know a good RDF-library written in pure Rust? What I found on crates.io didn’t match my requirements by now:

  • De- / serialization of RDF-graphs in TURTLE-annotation
  • Execution of SPARQL-querys
  • Manipulation of RDF-Graphs
  • Small footprint since I’m working on an Embedded System

I believe the main reason behind why *mut T doesn't implement Send and Sync is to act as a speed bump when doing this sort of thing (well, one of the reasons anyway). It makes you ask yourself whether you'll be using the raw pointer in a safe way. In this case you're putting it behind a mutex so we know it should be safe to access from multiple threads.

You could almost say that unsafe impl Send for Management {} is the idiomatic way to deal with these sorts of problems in Rust1. We use unsafe in order to build up safe abstractions and interfaces.

1 Assuming the use of unsafe is sound, of course. Which in this case means all use of the raw pointer is done via your mutex.