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 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..c48964b --- /dev/null +++ b/ctru-rs/examples/futures-basic.rs @@ -0,0 +1,73 @@ +//! 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()); + + // 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(); + let (mut timer_sender, mut timer_receiver) = futures::channel::mpsc::channel(0); + 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"); + } + } + } + }); + }) + .expect("Failed to create executor thread"); + + 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(); + } +}