Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop with two Waiters on the same event #16

Open
ennis opened this issue Sep 1, 2024 · 0 comments
Open

Infinite loop with two Waiters on the same event #16

ennis opened this issue Sep 1, 2024 · 0 comments

Comments

@ennis
Copy link

ennis commented Sep 1, 2024

use std::time::Duration;

use async_winit::event_loop::{EventLoop, EventLoopBuilder};
use async_winit::window::Window;
use async_winit::{DefaultThreadSafety, Timer};

use futures_lite::prelude::*;

fn main() {
    main2(EventLoopBuilder::new().build())
}

fn main2(evl: EventLoop) {
    let target = evl.window_target().clone();
    evl.block_on(async move {
        // Wait for a resume event to start.
        target.resumed().await;

        // Create a window.
        let window = Window::<DefaultThreadSafety>::new().await.unwrap();

        // Print resize events.
        let print_resize = {
            async {
                loop {
                    let new_size = window.resized().wait().await;
                    println!("(1) Window resized to {:?}", new_size);
                }
            }
        };

        let print_resize_again = {
            async {
                loop {
                    let new_size = window.resized().wait().await;
                    println!("(2) Window resized to {:?}", new_size);
                }
            }
        };

        // Wait for the window to close.
        async { window.close_requested().wait().await }
            .or(print_resize)
            .or(print_resize_again)  // comment this to make it work
            .await;

        // Exit.
        target.exit().await
    });
}

The above gets stuck in an infinite loop printing (1) and (2) alternatively:

(1) Window resized to PhysicalSize { width: 1904, height: 984 }
(2) Window resized to PhysicalSize { width: 1904, height: 984 }
(1) Window resized to PhysicalSize { width: 1904, height: 984 }
(2) Window resized to PhysicalSize { width: 1904, height: 984 }
...

With only one "print_resize" it works correctly. The issue might be in handler::Waiter. In my understanding, when a resize event is received:

  • one of the futures (say (1)) is notified
  • future (1) is polled, Waiter::poll_next notifies the next one in the chain (2).
  • future (1) immediately calls resized().wait() again, adding itself at the end of the list of listeners
  • future (2) is polled, Waiter::poll_next notifies the next one in the chain, i.e. (1) which just added itself
  • future (2) immediately calls resized().wait() again, adding itself at the end of the list of listeners
  • future (1) is polled, and this continues indefinitely
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant