0

I find myself playing around with warp.

I would like to pass a database Trait to a warp::Filter using static dispatch, such that the concrete database may vary.

I read that Send + Sync are unsafe to implement, but I don't fully understand when it is appropriate to implement them.

Is it sound to implement Send + Sync in this context:

use std::sync::{Arc, RwLock};

use warp::Filter;
use warp::reply::{json};
use serde_json::{Value};


pub trait IDatabase {
    fn db_read(&self) -> Value;
    fn db_write(&self, data: Value);
}

pub fn get_api_v0_test<T: IDatabase + Send + Sync>(
    db: Arc<RwLock<T>>
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
    warp::path!("api" / "v0" / "test")
        .and(warp::get())
        .map(move || {
            json(&db.read().unwrap().db_read())
        })
}

Edit:

Yes, this example is completely sound!

As @trentcl and @Masklinn pointed out, I am in fact not implementing Send + Sync, I am simply requiring that any type T passed into the filter, implements the Send + Sync Traits, which is completely safe Rust.

kruserr
  • 463
  • 4
  • 8
  • 3
    You aren't implementing `Send` and `Sync` in this code. You are *requiring* that the type `T` be a type which already implements `Send` and `Sync`. When you implement `Send` or `Sync`, you must use unsafe code, e.g. `unsafe impl Send for MyCustomType {}`. This is what it means that they are unsafe to implement. But they are safe to *use*, which is what you're doing here. – trent Oct 01 '21 at 12:14
  • 1
    Yes, in fact it would be unsound *not* to use it, which is why the compiler won't let the code compile unless you add `+ Send + Sync`. In Rust, as long as you don't use `unsafe`, you don't need to worry about data races or memory safety. – trent Oct 01 '21 at 12:20
  • Fantastic, I just seemed a bit confused that passing an abstract type seemed to require Send + Sync, where as passing a concrete type didn't. – kruserr Oct 01 '21 at 12:24
  • 1
    @kruserr yes here you're basically telling Rust to require that the parameter be `Send` and `Sync` (and `IDatabase`), which means the code inside the function can make use of those properties (which it needs). With a concrete type, the compiler knows the implemented traits and thus that the type is `Send` and `Sync`. Without those requirements, the corresponding properties are not assured so the code can not assume them. – Masklinn Oct 01 '21 at 12:31
  • 1
    This is similar to concept-based C++, but is a divergence from template-based C++ where the generics are first expanded (to whatever concrete type is used) then the capabilities are checked. In Rust the capabilities (reprensented by traits and trait bounds) are checked first. – Masklinn Oct 01 '21 at 12:33

1 Answers1

0

I read that Send + Sync are unsafe to implement, but I don't fully understand when it is appropriate to implement them.

Because Send and Sync are automatically derived, it is only appropriate to derive them explicitely when wrapping raw pointers, usually because you're wrapping a native library, and after having made sure that the trait is appropriate for the underlying type.

Is it sound to implement Send + Sync in this context:

I don't understand what you'd want to "implement Send + Sync" on in this context.

pub trait IDatabase {

Rust is not C#, IWhatever is not a thing.

Masklinn
  • 34,759
  • 3
  • 38
  • 57
  • Without implementing Send + Sync the compiler complains about them missing: ````T` cannot be sent between threads safely required because of the requirements on the impl of `Sync` for `std::sync::RwLock` required because of the requirements on the impl of `Send` for `std::sync::Arc>```` ...etc. – kruserr Oct 01 '21 at 12:07
  • `IWhatever` is just a naming convention also common for C++. – kruserr Oct 01 '21 at 12:13
  • I still don't understand what you would *implement* `Send` and `Sync` on here. Reminder: implementing them means `unsafe impl Send for `. Your snippet *requires* `Send` and `Sync` which is not unsafe and perfectly normal. It's a requirement, not an implementation. – Masklinn Oct 01 '21 at 12:25
  • Yes that was the confusion. I am in fact not implementing Send + Sync you are correct. – kruserr Oct 01 '21 at 12:26