Size: a a a

Rust — русскоговорящее сообществo

2020 October 27

Э

Эрик in Rust — русскоговорящее сообществo
antuan
немношк плавятся мозги. буду очень благодарен за помощь.
итак, есть вот такая структура с вот таким методом в сторонней либе (клиент для телеги)
pub struct Listener {
...
}
impl Listener {
  pub fn on_update_new_message<F>(&mut self, fnc: F) -> &mut Self
      where F: Fn((&EventApi, &UpdateNewMessage)) -> TGResult<()> + Send + Sync + 'static
     ...
  }
}

у меня есть вот такая над ней обертка:
pub struct TgClient {
client: Client
}

хочетя докинуть в структуру метод, который вызывал бы listener.on_update_new_message. в примерах из соответствуюшей илибы туда передается closure, но он создается в main'е, так что static-lifetime ок
и хочется, чтобы внутри closure жил mpsc::Sender, которой мог бы эти апдейты принимать и передавать куда-нибудь наружу

собсна, как сделал:
impl TgClient {
   fn start_listen_updates(&mut self, channel: Mutex<mpsc::Sender<Update>>) {  // mutex, т.к. Sender не реализует Sync
       let listener = self.client.listener();
       listener.on_update_new_message(get_new_message_handler(channel));
   }
}


fn get_new_message_handler(channel: Mutex<mpsc::Sender<Update>>) -> impl Fn((&EventApi, &UpdateNewMessage)) -> TGResult<()> + 'static {
   let local = channel.into_inner().unwrap().clone();
   move|(api, update)| {
       local.send(Update::NewMessage(update.clone())).unwrap();
       Ok(())
   }
}

компилятор ругается:
50  |         listener.on_update_new_message(get_new_message_handler(channel));
   |                  ^^^^^^^^^^^^^^^^^^^^^ `std::sync::mpsc::Sender<rtdlib::types::update::Update>` cannot be shared between threads safely
...
149 | fn get_new_message_handler(channel: Mutex<mpsc::Sender<Update>>) -> impl Fn((&EventApi, &UpdateNewMessage)) -> TGResult<()> + 'static {
   |                                                                     ----------------------------------------------------------------- within this `impl for<'r, 's> std::ops::Fn<((&'r telegram_client::api::aevent::EventApi, &'s rtdlib::types::update::UpdateNewMessage),)>`


существует ли решение? или канал не вариант и надо как-то через lazy_static всё делать с обработкой апдейтов непосредственно внутри замыкания?
>но он создается в main'е, так что static-lifetime
Нет, у всего, что создаётся внутри мейн функции лайфтайм не статик.
источник

a

antuan in Rust — русскоговорящее сообществo
Эрик
>но он создается в main'е, так что static-lifetime
Нет, у всего, что создаётся внутри мейн функции лайфтайм не статик.
и правда. тогда почему это работает?..
fn main() {
...
let listener = client.listener();
listener.on_update_option(|(api, option)| {
...
})
}


impl Listener {
  pub fn on_update_option<F>(&mut self, fnc: F) -> &mut Self
      where F: Fn((&EventApi, &UpdateOption)) -> TGResult<()> + Send + Sync + 'static {
  ...
  }
}
источник

a

antuan in Rust — русскоговорящее сообществo
предположительно, потому что листенер подыхает по завершении меина
источник

Э

Эрик in Rust — русскоговорящее сообществo
antuan
и правда. тогда почему это работает?..
fn main() {
...
let listener = client.listener();
listener.on_update_option(|(api, option)| {
...
})
}


impl Listener {
  pub fn on_update_option<F>(&mut self, fnc: F) -> &mut Self
      where F: Fn((&EventApi, &UpdateOption)) -> TGResult<()> + Send + Sync + 'static {
  ...
  }
}
Потому что если кложура не ловит окружение, у неё нет лайфтайма и её можно заборровить на 'static.
источник

a

antuan in Rust — русскоговорящее сообществo
что значит "не ловит окружение"?
источник

ИЛ

Иван Лещенко... in Rust — русскоговорящее сообществo
antuan
что значит "не ловит окружение"?
Захват локальных переменных
источник

Э

Эрик in Rust — русскоговорящее сообществo
Та же фигня с move, который мувит в себя 'static-only.
источник

a

antuan in Rust — русскоговорящее сообществo
а понял. с этим ок, спасибо.
а как быть с каналом?
источник

Э

Эрик in Rust — русскоговорящее сообществo
Если тебе таки надо 'static лайфтайм на что-то, что создаётся в рантайме, то юзай Box::leak или once_cell.
источник

a

antuan in Rust — русскоговорящее сообществo
и вообще. почему оборачивание в mutex не помогло? :(
источник

AV

Andrey Vlasov in Rust — русскоговорящее сообществo
С днём бегиннерсов в мейне!
источник

Э

Эрик in Rust — русскоговорящее сообществo
antuan
и вообще. почему оборачивание в mutex не помогло? :(
Как бы тебе сказать…
источник

Э

Эрик in Rust — русскоговорящее сообществo
Блин, а я не знаю, как рассказать о том, что мутекс без Arc не делает ничего, чего бы не делала структура сама по себе.
источник

a

antuan in Rust — русскоговорящее сообществo
Эрик
Блин, а я не знаю, как рассказать о том, что мутекс без Arc не делает ничего, чего бы не делала структура сама по себе.
рукалицо. точняк, спасибо. простите-извините за нубский вопрос.
источник

Э

Эрик in Rust — русскоговорящее сообществo
Не, есть вариант без Arc, но он включает в себя или статики, или Box::leak.
источник

MB

Mikail Bagishov in Rust — русскоговорящее сообществo
Эрик
Блин, а я не знаю, как рассказать о том, что мутекс без Arc не делает ничего, чего бы не делала структура сама по себе.
Он умеет Sync навешивать
источник

d

diabolo in Rust — русскоговорящее сообществo
Andrey Vlasov
С днём бегиннерсов в мейне!
уже два года как каждый день так
источник

a

antuan in Rust — русскоговорящее сообществo
запинили б хотя бы описалку в канале. а то не узнаешь, что есть @rust_beginners_ru.
задавал я там какой-то вопрос, который показался мне нубским. послали сюда /shrug
источник

AV

Andrey Vlasov in Rust — русскоговорящее сообществo
antuan
запинили б хотя бы описалку в канале. а то не узнаешь, что есть @rust_beginners_ru.
задавал я там какой-то вопрос, который показался мне нубским. послали сюда /shrug
В описании канала же есть
источник

a

antuan in Rust — русскоговорящее сообществo
запинили б хотя бы описалку в канале. а то не узнаешь, что есть @rust_beginners_ru, пока не посмотришь в описание канала)
вы вот, к слову, всегда заглядываете в описание каналов?
источник