Reputation: 1393
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.
Upvotes: 0
Views: 379
Reputation: 73480
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:
Upvotes: 2