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

Oh hells to the yes. #3

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions static-cassette-demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
37 changes: 37 additions & 0 deletions static-cassette-demo/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions static-cassette-demo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "static-cassette"
version = "0.1.0"
authors = ["James Munns <james.munns@ferrous-systems.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cassette = "0.2.2"
static-alloc = "0.2.2"
once_cell = "1.7.2"
150 changes: 150 additions & 0 deletions static-cassette-demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use static_alloc::Bump;
use once_cell::sync::OnceCell;
use std::sync::Mutex;
use core::{
future::Future,
pin::Pin,
sync::atomic::{AtomicU32, Ordering},
task::{Context, Poll},
};

use cassette::Cassette;

static A: Bump<[u8; 128]> = Bump::uninit();
static OML: OnceCell<Mutex<Yolo>> = OnceCell::new();

struct Yolo {
ip: Cassette<Pin<&'static mut (dyn Future<Output = ()> + Send)>>
}

fn main() {
println!("Hello, world!");

// Setup...

// Leak the object...
let leaked_demo = A.leak(Demo { lol: 100 }).map_err(drop).unwrap();

// Leak the future...
let leaked = A.leak(leaked_demo.entry()).map_err(drop).unwrap();

// Coerce it to a dyn Future...
let deu: &mut (dyn Future<Output=()> + Send) = leaked;

// Pin it...
let pdeu = unsafe { core::pin::Pin::new_unchecked(deu) };

// Slam that future in the Cassette...
let cas = Cassette::new(pdeu);

// Stick the Cassette in a mutex oncecell to simulate
// RTIC's `Resource`s
OML.set(Mutex::new(Yolo { ip: cas })).map_err(drop).unwrap();

// Run...
std::thread::spawn(|| {
loop {
// Look! An interrupt occurred!
fake_rtic_outer();
}
}).join();
}

fn fake_rtic_outer() {
// This is simulating the guts of RTIC that gets the resource
// and passes it into a task
let mut ctxt = OML.get().unwrap().lock().unwrap();
fake_rtic_inner(&mut ctxt);
}

fn fake_rtic_inner(ctxt: &mut Yolo) {
// This is simulating an RTIC task
match ctxt.ip.poll_on() {
Some(data) => {
panic!("Failed successfully: {:?}", data);
}
None => {
println!("werk.");
}
}
}

///////////////////////////////////////////
// This is all the async state machine code
// I used when I wrote Cassette...

struct Demo {
lol: u32,
}

impl Demo {
async fn entry(&mut self) {
for _ in 0..10 {
self.entry_1().await;
self.entry_2().await;
}
}

async fn entry_1(&mut self) {
self.start_at_zero().await;
self.add_one_until_ten().await;
self.sub_one_until_zero().await;
}

async fn entry_2(&mut self) {
self.start_at_five().await;
self.sub_one_until_zero().await;
self.add_one_until_ten().await;
}

async fn start_at_zero(&mut self) {
self.lol = 0;
}

async fn start_at_five(&mut self) {
self.lol = 5;
}

async fn add_one_until_ten(&mut self) {
loop {
delay(self).await; // simulate fake delays/not ready state
self.lol += 1;
if self.lol >= 10 {
return;
}
}
}

async fn sub_one_until_zero(&mut self) {
loop {
delay(self).await; // simulate fake delays/not ready state
self.lol -= 1;
if self.lol == 0 {
return;
}
}
}
}


static FAKE: AtomicU32 = AtomicU32::new(0);
struct CountFuture;
impl Future for CountFuture {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
let x = FAKE.fetch_add(1, Ordering::SeqCst);
print!("{}, ", x);
if (x % 5) == 0 {
Poll::Ready(())
} else {
Poll::Pending
}
}
}

async fn delay(ctxt: &mut Demo) {
println!("delay says lol: {}", ctxt.lol);
let x = CountFuture;
x.await;
println!("and delay!");
}