From aed2684db55ac04496fe1a7dc7a4a37ce02bcfc9 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 24 Feb 2022 17:03:39 -0500 Subject: stop using tokio::select! --- Cargo.lock | 102 +++++++++++++++++++++++++++++ Cargo.toml | 1 + src/bin/ttyplay/timer.rs | 167 +++++++++++++++++++++++++---------------------- 3 files changed, 192 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5ab15a..18e6301 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,6 +74,95 @@ dependencies = [ "vec_map", ] +[[package]] +name = "futures" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-macro" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "heck" version = "0.3.3" @@ -257,6 +346,12 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -333,6 +428,12 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + [[package]] name = "smallvec" version = "1.8.0" @@ -477,6 +578,7 @@ name = "ttyrec-bin" version = "0.1.3" dependencies = [ "anyhow", + "futures", "libc", "paw", "pty-process", diff --git a/Cargo.toml b/Cargo.toml index 47665fc..aa1e9bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] [dependencies] anyhow = "1.0.55" +futures = "0.3.21" libc = "0.2.119" paw = "1.0.0" pty-process = { version = "0.2.0", features = ["async"] } diff --git a/src/bin/ttyplay/timer.rs b/src/bin/ttyplay/timer.rs index 2f99786..e8dc0fa 100644 --- a/src/bin/ttyplay/timer.rs +++ b/src/bin/ttyplay/timer.rs @@ -1,3 +1,5 @@ +use futures::future::FutureExt as _; + pub fn spawn_task( event_w: tokio::sync::mpsc::UnboundedSender, frames: std::sync::Arc>, @@ -8,6 +10,11 @@ pub fn spawn_task( speed: u32, ) -> tokio::task::JoinHandle<()> { tokio::task::spawn(async move { + enum Res { + Frame(Option>), + Action(Option), + } + let mut idx = 0; let mut start_time = std::time::Instant::now(); let mut paused_time = if pause_at_start { @@ -62,8 +69,14 @@ pub fn spawn_task( None } }; - tokio::select! { - screen = wait => if let Some(screen) = screen { + let select: futures::future::SelectAll<_> = [ + wait.map(Res::Frame).boxed(), + timer_r.recv().map(Res::Action).boxed(), + ] + .into_iter() + .collect(); + match select.map(|(res, _, _)| res).await { + Res::Frame(Some(screen)) => { event_w .send(crate::event::Event::FrameTransition(( idx, screen, @@ -72,105 +85,103 @@ pub fn spawn_task( .unwrap(); idx += 1; } - else { + Res::Frame(None) => { idx = frames.clone().lock_owned().await.count() - 1; paused_time = Some(std::time::Instant::now()); event_w .send(crate::event::Event::Paused(true)) // event_w is never closed, so this can never fail .unwrap(); - }, - action = timer_r.recv() => match action { - Some(action) => match action { - crate::event::TimerAction::Pause => { - let now = std::time::Instant::now(); - paused_time.take().map_or_else(|| { + } + Res::Action(Some(action)) => match action { + crate::event::TimerAction::Pause => { + let now = std::time::Instant::now(); + paused_time.take().map_or_else( + || { paused_time = Some(now); - }, |time| { + }, + |time| { start_time += now - time; - }); + }, + ); + event_w + .send(crate::event::Event::Paused( + paused_time.is_some(), + )) + // event_w is never closed, so this can never fail + .unwrap(); + } + crate::event::TimerAction::FirstFrame => { + idx = 0; + force_update_time = true; + } + crate::event::TimerAction::LastFrame => { + idx = frames.clone().lock_owned().await.count() - 1; + force_update_time = true; + } + // force_update_time will immediately transition to the + // next frame and do idx += 1 on its own + crate::event::TimerAction::NextFrame => { + force_update_time = true; + } + crate::event::TimerAction::PreviousFrame => { + idx = idx.saturating_sub(2); + force_update_time = true; + } + crate::event::TimerAction::SpeedUp => { + if playback_ratio > 1 { + playback_ratio /= 2; + let now = std::time::Instant::now(); + start_time = now - (now - start_time) / 2; event_w - .send(crate::event::Event::Paused( - paused_time.is_some(), + .send(crate::event::Event::Speed( + playback_ratio, )) // event_w is never closed, so this can never // fail .unwrap(); } - crate::event::TimerAction::FirstFrame => { - idx = 0; - force_update_time = true; - } - crate::event::TimerAction::LastFrame => { - idx = - frames.clone().lock_owned().await.count() - 1; - force_update_time = true; - } - // force_update_time will immediately transition to the - // next frame and do idx += 1 on its own - crate::event::TimerAction::NextFrame => { - force_update_time = true; - } - crate::event::TimerAction::PreviousFrame => { - idx = idx.saturating_sub(2); - force_update_time = true; - } - crate::event::TimerAction::SpeedUp => { - if playback_ratio > 1 { - playback_ratio /= 2; - let now = std::time::Instant::now(); - start_time = now - (now - start_time) / 2; - event_w - .send(crate::event::Event::Speed( - playback_ratio, - )) - // event_w is never closed, so this can - // never fail - .unwrap(); - } - } - crate::event::TimerAction::SlowDown => { - if playback_ratio < 256 { - playback_ratio *= 2; - let now = std::time::Instant::now(); - start_time = now - (now - start_time) * 2; - event_w - .send(crate::event::Event::Speed( - playback_ratio, - )) - // event_w is never closed, so this can - // never fail - .unwrap(); - } - } - crate::event::TimerAction::DefaultSpeed => { + } + crate::event::TimerAction::SlowDown => { + if playback_ratio < 256 { + playback_ratio *= 2; let now = std::time::Instant::now(); - start_time = now - - (((now - start_time) * 16) / playback_ratio); - playback_ratio = 16; + start_time = now - (now - start_time) * 2; event_w - .send( - crate::event::Event::Speed(playback_ratio) - ) + .send(crate::event::Event::Speed( + playback_ratio, + )) // event_w is never closed, so this can never // fail .unwrap(); } - crate::event::TimerAction::Search(s, backwards) => { - if let Some(new_idx) = - frames.clone() - .lock_owned() - .await - .search(idx, &s, backwards) - { - idx = new_idx; - force_update_time = true; - } + } + crate::event::TimerAction::DefaultSpeed => { + let now = std::time::Instant::now(); + start_time = now + - (((now - start_time) * 16) / playback_ratio); + playback_ratio = 16; + event_w + .send(crate::event::Event::Speed(playback_ratio)) + // event_w is never closed, so this can never fail + .unwrap(); + } + crate::event::TimerAction::Search(s, backwards) => { + if let Some(new_idx) = frames + .clone() + .lock_owned() + .await + .search(idx, &s, backwards) + { + idx = new_idx; + force_update_time = true; } - crate::event::TimerAction::Quit => break, } - None => unreachable!(), + crate::event::TimerAction::Quit => break, }, + Res::Action(None) => { + unreachable!() + } } } }) -- cgit v1.2.3-54-g00ecf