Почему опрос Mio запускается дважды для пользовательских событий? - PullRequest
0 голосов
/ 03 мая 2018

Следующий код генерирует «пользовательское событие», которое будет возвращено poll:

extern crate mio;

use mio::event::Evented;
use mio::{Events, Poll, PollOpt, Ready, Registration, Token};
use std::thread::{sleep, spawn, JoinHandle};
use std::time::{Duration, Instant};

#[derive(Debug)]
struct Output(u32, Duration);

pub struct MioThread {
    registration: Registration,
    handle: JoinHandle<Output>,
}

impl MioThread {
    pub fn new(i: u32) -> MioThread {
        let now = Instant::now();

        let (registration, set_readiness) = Registration::new2();

        let handle = spawn(move || {
            sleep(Duration::from_millis((1000 - (100 * i)) as u64));

            set_readiness.set_readiness(Ready::readable()).unwrap();

            Output(i, now.elapsed())
        });

        MioThread {
            registration: registration,
            handle: handle,
        }
    }

    // manage the thread result
    fn eval_result(self) {
        let out = self.handle.join();
        println!("do whathever you want with: {:?}", out.unwrap());
    }
}

fn main() {
    let poll = Poll::new().unwrap();

    let mut events = Events::with_capacity(16);

    let mut tasks = Vec::new();
    for i in 0..5 {
        let mio_thread = MioThread::new(i);

        mio_thread
            .registration
            .register(&poll, Token(i as usize), Ready::readable(), PollOpt::edge())
            .unwrap();

        tasks.push(Some(mio_thread));
    }

    loop {
        let num_events = poll.poll(&mut events, None).unwrap();
        println!("poll fired: {} events", num_events);
        for event in &events {
            if event.readiness().is_readable() {
                let Token(thread_id) = event.token();

                if let Some(t) = tasks.remove(thread_id) {
                    t.eval_result();
                }

            }
        }
    }
}

Вывод:

poll fired: 1 events
do whathever you want with: Output(4, Duration { secs: 0, nanos: 600967623 })
poll fired: 0 events
poll fired: 1 events
do whathever you want with: Output(3, Duration { secs: 0, nanos: 701035026 })
poll fired: 0 events
poll fired: 1 events
do whathever you want with: Output(2, Duration { secs: 0, nanos: 801089370 })
poll fired: 0 events
poll fired: 1 events
do whathever you want with: Output(1, Duration { secs: 0, nanos: 900890190 })
poll fired: 0 events
poll fired: 1 events
do whathever you want with: Output(0, Duration { secs: 1, nanos: 600076 })
poll fired: 0 events

Я открыл проблему в хранилище Mio .

1 Ответ

0 голосов
/ 08 мая 2018

Как указано в комментариях и подтверждено здесь :

удаление Регистрации может пробудить цикл (что он действительно делает, так же, как регистрация) без фактического запуска события

Это, очевидно, не проблема в большинстве случаев, просто поведение, которого я не ожидал после прочтения документов :

fn poll (& self, events: & mut Events, timeout: Option) -> Result [-] Ждите событий готовности

Блокирует текущий поток и ожидает событий готовности для любого из дескрипторов Evented, которые были зарегистрированы в этом экземпляре опроса. Функция блокируется до тех пор, пока не будет получено хотя бы одно событие готовности или истечет время ожидания. Тайм-аут None означает, что опрос будет блокироваться до тех пор, пока не будет получено событие готовности.

Текущий поток действительно пробуждается и при сбросе Registration.

...