Search code examples
rusttrait-objects

Trait object cannot be shared between threads safely


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.


Solution

  • 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>,
    }