gpio-cdev icon indicating copy to clipboard operation
gpio-cdev copied to clipboard

Non-blocking polling of events

Open svenvdvoort opened this issue 5 years ago • 2 comments

Hello,

Thank you for providing us with this wonderful library! A missing feature of this library to me is the ability to do a non-blocking poll on the LineEventHandle struct. Currently every method (.get_event(), .next() and .read_event()) is blocking. Ideally we would have a sort of .has_event() -> bool function available to check whether there is an event available to process. This way we would take maximum advantage of the queue-like architecture of the new GPIO character device ABI.

Please let me know what you think of this suggestion.

Cheers, Sven.

svenvdvoort avatar Nov 15 '20 12:11 svenvdvoort

hmm is this for async or sync use? in the async case would .poll_next() per the standard stream implementation work?

in the blocking case this seems like it could be useful, perhaps a .try_get_event() -> Option<bool> or similar?

ryankurte avatar Mar 06 '21 22:03 ryankurte

Hi, I do not know how @svenvdvoort plans to use, but I am searching to someway impletent a timeout for the .read_event(): a process starts a request for a GPIO interaction from the user and, if there is no input for a Duration, the code continues with a timeout. I tried this with select!, but the result was very unstable.

pub async fn confirma_giro(&self, timeout: Duration) -> LeitorResult<()> {
    let _handle_confirm = match self.gpio_confirm.events(
        gpio_cdev::LineRequestFlags::INPUT,
        gpio_cdev::EventRequestFlags::FALLING_EDGE,
        &(self.sentido.to_string() + "_GPIO_CONFIRM"),
    ) {
        Ok(value) => value,
        Err(e) => return Err(LeitorError::GPIO { kind: e }),
    };

    let timeout = async {
        thread::sleep(timeout);
    };

    let giro = Box::pin(async {
        // *** Aguarda o sinal chegar ao estado desligado
        match _handle_confirm.get_value() {
            Ok(sinal) => {
                if sinal != SIGNAL_OFF {
                    return Err(LeitorError::ConfirmaGiroIncorreto);
                }
            }
            Err(e) => return Err(LeitorError::GPIO { kind: e }),
        };

        if let Ok(_e) = _handle_confirm.get_event() {
            thread::sleep(Duration::from_millis(100));

            if let Ok(sinal) = _handle_confirm.get_value() {
                if sinal == SIGNAL_ON {
                    return Ok(());
                }
            }
            return Err(LeitorError::SinalInstavel);
        }
        Err(LeitorError::ConfirmaGiroIncorreto)
    });

    select! {
        resp = giro.fuse() => resp,
        _out = timeout.fuse() => Err(LeitorError::TimeOut),
    }
}

MarceloAlm avatar Jun 28 '21 17:06 MarceloAlm