Невозможно отправить структуру через потоки, в которой есть поле mps c :: Sender - PullRequest
0 голосов
/ 09 июля 2020

У меня есть структура с типом Sender в качестве поля.

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

Я использую структуру в нескольких потоках, поэтому, используя ее внутри Ar c и клонирую ее .

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));
        });
    }
}

Но я получаю сообщение об ошибке, что моя структура не может быть отправлена ​​по потокам.

`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>>]`

Я понял, что тип Sender нельзя безопасно отправлять по потокам , но поскольку это cloneable, вы можете клонировать его, а затем отправить по потоку. Но в моей ситуации отправитель находится внутри моей структуры. Я не могу придумать, как это исправить.

Я думаю, мне, возможно, придется изменить свой дизайн.

1 Ответ

1 голос
/ 10 июля 2020

Вы можете использовать Crossbeam. Его crossbeam::Sender кажется передаваемым между потоками. Предположительно, вам также нужно будет использовать его crossbeam::Receiver.

В качестве альтернативы вы можете реорганизовать свой GenericConnectionPool, чтобы он был таким:

pub struct ExtraData {}

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

, тогда вы можете клонировать GenericConnectionPool напрямую, а не Ar c, содержащий его, и получите правильное поведение:

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));
    });
}

Вы можете увидеть версию компиляции здесь :

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...