In-memory store and `Sync`

Hi,

this is a reduced example: (moved from GitHub to the Rust playground, see link below)

I want to pass a mutable reference to a dyn StoreTrait to hyper so that it can be modified from a web GUI.

It's possible that the store is in-memory, which is why i don't want it to be Send, just Sync. The current version does not compile:

(dyn StoreTrait + std::marker::Sync + 'static)` cannot be sent between threads safely

I'd appreciate any suggestions to make a mutable in-memory store work via warp.

I'm not sure what you mean with not needing Send due to some in-memory thing? You should probably just add Send.

Hi, to be honest, i am a bit lost here.

If i made the trait Send, doesn't that mean that the in-memory data is duplicated and only the duplicates are modified? I had the hope that with arc/mutext only the arc/mutex are duplicated, not the data.

If the type is Send, its ownership can be transferred to other thread. If the type is Sync, its shared references can be sent to other thread so it can be placed on global variable. That's all and it's enough to prevent data race statically, and it enables refcounted smart pointer with non-atomic counter.

Rust only implicitly duplicates Copy types, everything else must be cloned explicitly.

"Sending" things to a thread is not an actual operation, just a theoretical type-system check.

When adding a Send it gives

move occurs because data has type std::sync::Arc<tokio::sync::mutex::Mutex<std::boxed::Box<&mut dyn StoreTrait + std::marker::Send + std::marker::Sync>>>, which does not implement the Copy trait

Copying the in-memory store itself would not be desired. I am looking for a way to just hand around mutable references to the in-memory store to the threads.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=237ba9f40ce565ae4dbfb8cef0403b36

You should just be using

pub type Data = Arc<Mutex<Box<dyn StoreTrait + Sync + Send>>>;

without the reference. The Arc already handles sharing without cloning the store itself, the mutex ensures mutable access is possible, and the box ensures you can use a trait object instead of a concrete struct.

As for the missing Copy trait, the new handle to the Arc you created in the start of make_service_fn is indeed moved into the async block, and then into the closure in service_fn. The issue is that the closure in service_fn can be called multiple times, so it can't give ownership of it's handle to the data store away. You can fix this by making another handle to the shared data store:

hyper::service::service_fn(move |request| reply(data.clone(), request)),

playground

Thank you, alice and all.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.