Pauan / rust-signals

Zero-cost functional reactive Signals for Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SignalVecExt::flatten stops polling after first top-level item if the item is empty

martin-kolarik opened this issue · comments

If the first polled item of flatten is empty SignalVec, inner polling of this SignalVec ends with Pending, and therefore top-level poll loop does not continue. If top-level SignalVec contains more items in this situation, they are not polled immediately and wait until next wake up.

Thanks for the report, but I'm having a hard time reproducing it. Could you give an example which fails?

I apologize, I will provide code later, I am a bit short of time now.

It will be something like (not tested):

let a = MutableVec<MutableVec<u32>>::new();
a.lock_mut().push_cloned(MutableVec::new());
a.lock_mut().push_cloned(MutableVec::new_with_values(vec![15]));

let s = a.signal_vec_cloned().map(|v| v.signal_vec()).flatten();

The behavior in handling Flatten then is that the first (top-level) VecDiff::Push is loaded and stored into this.inner, but then polling stops (my continue solves it in the proposed fix), so the next VecDiff::Push carrying vec![15] is delayed till next wakeup.

So, here is the code:

use std::future::ready;

use async_std::task::{sleep, spawn};
use futures_signals::signal_vec::{MutableVec, SignalVecExt};

#[async_std::main]
async fn main() {
    let outer: MutableVec<MutableVec<usize>> = MutableVec::new();

    let flattened = outer
        .signal_vec_cloned()
        .map(|inner| inner.signal_vec())
        .flatten();

    spawn(flattened.map(|x| println!("{x}")).for_each(|_| ready(())));

    sleep(std::time::Duration::from_secs(1)).await;

    outer.lock_mut().push_cloned(MutableVec::new());
    outer
        .lock_mut()
        .push_cloned(MutableVec::new_with_values(vec![42]));

    loop {
        sleep(std::time::Duration::from_secs(1)).await;
    }
}

The sleep afer spawn ensures in a dirty way that spawn starts polling before values are inserted.

If flatten implementation uses continue, as in #80, it prints out 42. If flatten uses false, as in current 0.3.33 code, it prints out nothing.

Sorry about the delay on this, I've been quite busy. Your example was helpful, and I've fixed this.