0

I have a struct which has Sender type as its field.

pub struct GenericConnectionPool<E>
where
    E: ConnectionConnector,
{
    _sender: Sender<()>,
    _reciever: Arc<Mutex<Receiver<()>>>,
    _num_of_live_connections: AtomicU8,
    _max_connections: u8,
    _min_connections: u8,
    _connections: Arc<Mutex<Vec<<E as ConnectionConnector>::Conn>>>,
    _connector: E,
}

I am using the struct across multiple threads, that is why, while using it inside Arc and clone it.

let pool = Arc::new(GenericConnectionPool::new(2, 1, cc));
println!("here");
{
    for _ in 0..3 {
        let pool = Arc::clone(&pool);
        std::thread::spawn(move || {
            pool.get_connection();
            thread::sleep(Duration::from_secs(1));
        });
    }
}

But I am getting the error that my struct cannot be sent across threads.

`std::sync::mpsc::Sender<()>` cannot be shared between threads safely
within `GenericConnectionPool<tests::connector_works::DummyConnectionConnector>`, the trait `std::marker::Sync` is not implemented for `std::sync::mpsc::Sender<()>`
required because it appears within the type `GenericConnectionPool<tests::connector_works::DummyConnectionConnector>`
required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<GenericConnectionPool<tests::connector_works::DummyConnectionConnector>>`
required because it appears within the type `[closure@src/lib.rs:169:36: 172:18 pool:std::sync::Arc<GenericConnectionPool<tests::connector_works::DummyConnectionConnector>>]`

What I understood is that the Sender type cannot be sent safely across threads, but since its cloneable, you can clone it and then send it across the thread. But in my situation, sender is inside my Struct. I can't figure out a way to fix this.

I am thinking I might have to change my design.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
kumarmo2
  • 1,381
  • 1
  • 20
  • 35
  • 1
    Does this answer your question? [Rust mpsc::Sender cannot be shared between threads?](https://stackoverflow.com/questions/40384274/rust-mpscsender-cannot-be-shared-between-threads) – Aunmag Dec 18 '20 at 09:51

1 Answers1

2

You could use Crossbeam. Its crossbeam::Sender seems to be transferable between threads. Presumably, you'd need to use its crossbeam::Receiver too.

Alternatively, you could refactor your GenericConnectionPool to be like this:

pub struct ExtraData {}

#[derive(Clone)]
pub struct GenericConnectionPool {
    _sender: Sender<()>,
    _extra_data: Arc<ExtraData>,
}

then you can clone the GenericConnectionPool directly rather than an Arc containing it and get the correct behaviour:

let pool = GenericConnectionPool{_sender:s, _extra_data:Arc::new(ExtraData{}) };

for _ in 0..3 {
   let pool = pool.clone();
   std::thread::spawn(move || {
       pool.get_connection();
       thread::sleep(Duration::from_secs(1));
    });
}

You can see a compiling version here:

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
  • This is exactly what i decided to go with. https://github.com/kumarmo2/connection-pool/blob/master/src/lib.rs#L53 . But I will also look at the crossbeam library, you have mentioned. Thanks a lot. – kumarmo2 Jul 10 '20 at 05:21