1

When I am writing a zookeeper client in RUST.

code like this :

pub trait ZookeeperHandler {
    fn on_child_change(&self, path : &str, value : &String);
    fn on_valude_change(&self, path : &str, value: String);
    fn reload_all_child(&self, path : &str, children : HashMap<String, String>);
}

pub struct WatchNode  {
    path : String,
    node_type: i32,
    handler : Box<dyn ZookeeperHandler>,
}

pub struct WatchNodeManager {
    watch_nodes : HashMap<String, WatchNode>,
}

impl  WatchNodeManager  {
    //do something
}

pub struct ZKProxy {
    init : bool,
    address: String,
    zk : Option<ZooKeeper>,
    watch_nodes : WatchNodeManager,
}

lazy_static! {
    pub static ref ZK_PROXY : Box<ZKProxy> = Box::new(ZKProxy::new(String::from("127.0.0.1:2081")));
}

This fails with the following message:

   |
59 | / lazy_static! {
60 | |     pub static ref ZK_PROXY : Box<ZKProxy> = Box::new(ZKProxy::new(String::from("127.0.0.1:2081")));
61 | | }
   | |_^ `(dyn ZookeeperHandler + 'static)` cannot be shared between threads safely
   |

As a beginner of RUST, I can't figure out what this error means and how to fix it.

Herohtar
  • 5,347
  • 4
  • 31
  • 41
dongwei
  • 23
  • 2

1 Answers1

2

As global statics can be accessed by multiple threads at the same time, they have to be thread safe. Objects can have the auto-trait Sync that indicates that they are thread-safe.

Unless something prevents that, all types are Send + Sync. In your case, though, your type contains a Box<dyn Zookeeper>, which is neither Send nor Sync, because it could be anything that is dyn Zookeeper. You need to tell Rust that this only accepts Sync objects:

pub struct WatchNode {
    path: String,
    node_type: i32,
    handler: Box<dyn ZookeeperHandler + Sync>,
}
Finomnis
  • 18,094
  • 1
  • 20
  • 27
  • If `Box` was a type from another crate that you can't modify (i.e. `Display, ST7789, OutputPin>`), is `Mutex` a good option? – Martin Schaer Aug 27 '23 at 09:13
  • @MartinSchaer Yes, I would say so. [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) converts a objects that are only `Send` to objects that are `Send+Sync`. That said, your `SPIInterfaceNoCS` indicates that this is actually an embedded `no-std` project. Be aware that there is no platform independent way of implementing a mutex, so in many cases, a `no-std` platform does not **have** a mutex. And many `no-std` mutexes (such as the one based on [`critical_section`](https://docs.rs/critical-section/latest/critical_section/)) work a little different. – Finomnis Aug 27 '23 at 16:52