Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Curious if there's a nicer way to (ab)use async as co-routines without Box
I'm trying to figure out if I can simplify my emulator logic by representing each bit of hardware with an async function that can just cycles(3).await
rather than building a state machine.
Messing around a bit it's easy enough to do with Box::pin()
and I expect I'll end up just using that, but I was wondering how far I could push it without any indirection at all, and I came up with this, err, gem:
#![feature(type_alias_impl_trait)]
use std::cell::Cell;
use std::future::Future;
use std::pin::{pin, Pin};
use std::time::Duration;
fn main() {
let mut vm = pin!(Vm::new());
loop {
vm.as_mut().step();
std::thread::sleep(Duration::from_millis(500));
}
}
pin_project_lite::pin_project! {
struct Vm {
cycles: u32,
#[pin]
foo: Foo,
#[pin]
bar: Bar,
}
}
impl Vm {
fn new() -> Self {
Self {
cycles: 0,
foo: foo(),
bar: bar(),
}
}
fn step(self: Pin<&mut Self>) {
let mut this = self.project();
*this.cycles = this.cycles.wrapping_add(1);
CYCLES.set(*this.cycles);
let waker = std::task::Waker::noop();
let mut cx = std::task::Context::from_waker(waker);
_ = this.foo.as_mut().poll(&mut cx);
_ = this.bar.as_mut().poll(&mut cx);
}
}
thread_local! {
static CYCLES: Cell<u32> = const { Cell::new(0) };
}
async fn cycles(count: u32) {
let deadline = CYCLES.get().wrapping_add(count);
let fut = std::future::poll_fn(move |_cx| {
if CYCLES.get() < deadline {
std::task::Poll::Pending
} else {
std::task::Poll::Ready(())
}
});
fut.await
}
type Foo = impl Future;
#[define_opaque(Foo)]
fn foo() -> Foo {
async {
loop {
cycles(3).await;
println!("foo");
}
}
}
type Bar = impl Future;
#[define_opaque(Bar)]
fn bar() -> Bar {
async {
loop {
cycles(5).await;
println!("bar");
}
}
}
Is this about where the state of the art is here, am I missing any nicer ways to do this, or should I be looking into other nightly features (generators?) if I'm trying to pull this?
1 post - 1 participant
🏷️ Rust_feed