From 4dd2196971772a910849fdb9423c51549dae2a23 Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Mon, 31 Jan 2022 20:01:25 -0800 Subject: [PATCH 1/4] Add a basic futures example --- ctru-rs/Cargo.toml | 1 + ctru-rs/examples/futures-basic.rs | 66 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 ctru-rs/examples/futures-basic.rs diff --git a/ctru-rs/Cargo.toml b/ctru-rs/Cargo.toml index 1b303f3..4635fa6 100644 --- a/ctru-rs/Cargo.toml +++ b/ctru-rs/Cargo.toml @@ -25,6 +25,7 @@ toml = "0.5" [dev-dependencies] ferris-says = "0.2.1" +futures = "0.3" time = "0.3.7" [features] diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs new file mode 100644 index 0000000..5cac1fb --- /dev/null +++ b/ctru-rs/examples/futures-basic.rs @@ -0,0 +1,66 @@ +//! This example runs a basic future executor from the `futures` library. +//! Every 60 frames (about 1 second) it prints "Tick" to the console. +//! The executor runs on a separate thread. Internally it yields when it has no more work to do, +//! allowing other threads to run. +//! The example also implements clean shutdown by using a oneshot channel to end the future, thus +//! ending the executor and the thread it runs on. + +use ctru::console::Console; +use ctru::services::hid::KeyPad; +use ctru::services::{Apt, Hid}; +use ctru::Gfx; +use futures::StreamExt; + +fn main() { + ctru::init(); + let gfx = Gfx::default(); + let hid = Hid::init().expect("Couldn't obtain HID controller"); + let apt = Apt::init().expect("Couldn't obtain APT controller"); + let _console = Console::init(gfx.top_screen.borrow_mut()); + + println!("Starting executor..."); + + let (exit_sender, mut exit_receiver) = futures::channel::oneshot::channel(); + let (mut timer_sender, mut timer_receiver) = futures::channel::mpsc::channel(0); + let executor_thread = ctru::thread::spawn(move || { + let mut executor = futures::executor::LocalPool::new(); + + executor.run_until(async move { + loop { + futures::select! { + _ = exit_receiver => break, + _ = timer_receiver.next() => { + println!("Tick"); + } + } + } + }); + }); + + println!("Executor started!"); + + let mut frame_count = 0; + while apt.main_loop() { + hid.scan_input(); + + if hid.keys_down().contains(KeyPad::KEY_START) { + println!("Shutting down..."); + let _ = exit_sender.send(()); + let _ = executor_thread.join(); + break; + } + + frame_count += 1; + + if frame_count == 60 { + if let Err(e) = timer_sender.try_send(()) { + println!("Error sending timer message: {e}"); + } + frame_count = 0; + } + + gfx.flush_buffers(); + gfx.swap_buffers(); + gfx.wait_for_vblank(); + } +} From 5c5ac7ef6686b5fecd9b8471a30292aabe9801ee Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Mon, 31 Jan 2022 20:01:41 -0800 Subject: [PATCH 2/4] Ignore IDE files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c34b8d3..54f1838 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ target Cargo.lock .cargo + +# IDE files +.idea From c13c1c8c6855513cecdf08be677cd99c9b55cdbd Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Tue, 1 Feb 2022 17:07:43 -0800 Subject: [PATCH 3/4] Run executor thread on system core --- ctru-rs/examples/futures-basic.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs index 5cac1fb..77d20ca 100644 --- a/ctru-rs/examples/futures-basic.rs +++ b/ctru-rs/examples/futures-basic.rs @@ -22,20 +22,23 @@ fn main() { let (exit_sender, mut exit_receiver) = futures::channel::oneshot::channel(); let (mut timer_sender, mut timer_receiver) = futures::channel::mpsc::channel(0); - let executor_thread = ctru::thread::spawn(move || { - let mut executor = futures::executor::LocalPool::new(); + let executor_thread = ctru::thread::Builder::new() + .affinity(1) + .spawn(move || { + let mut executor = futures::executor::LocalPool::new(); - executor.run_until(async move { - loop { - futures::select! { - _ = exit_receiver => break, - _ = timer_receiver.next() => { - println!("Tick"); + executor.run_until(async move { + loop { + futures::select! { + _ = exit_receiver => break, + _ = timer_receiver.next() => { + println!("Tick"); + } } } - } - }); - }); + }); + }) + .expect("Failed to create executor thread"); println!("Executor started!"); From 39adc8590e0806767b1498d3e025409688b301f0 Mon Sep 17 00:00:00 2001 From: AzureMarker Date: Tue, 1 Feb 2022 18:30:49 -0800 Subject: [PATCH 4/4] Enable the system core by setting our time limit percentage --- ctru-rs/examples/futures-basic.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ctru-rs/examples/futures-basic.rs b/ctru-rs/examples/futures-basic.rs index 77d20ca..c48964b 100644 --- a/ctru-rs/examples/futures-basic.rs +++ b/ctru-rs/examples/futures-basic.rs @@ -18,6 +18,10 @@ fn main() { let apt = Apt::init().expect("Couldn't obtain APT controller"); let _console = Console::init(gfx.top_screen.borrow_mut()); + // Give ourselves up to 30% of the system core's time + apt.set_app_cpu_time_limit(30) + .expect("Failed to enable system core"); + println!("Starting executor..."); let (exit_sender, mut exit_receiver) = futures::channel::oneshot::channel();