Initial commit

This commit is contained in:
Daniella / Tove 2024-07-14 01:56:36 +00:00
commit 54e908530d
7 changed files with 167 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

16
Cargo.lock generated Normal file
View file

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "microasync"
version = "0.1.0"
dependencies = [
"microlock",
]
[[package]]
name = "microlock"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "849d9daa132b37b3082c2ef186343573aedf6ebc7e1b57343e9278e81a2b5b20"

7
Cargo.toml Normal file
View file

@ -0,0 +1,7 @@
[package]
name = "microasync"
version = "0.1.0"
edition = "2021"
[dependencies]
microlock = "0.2.0"

13
examples/basic.rs Normal file
View file

@ -0,0 +1,13 @@
use std::time::Duration;
use microasync::rt::{MiniAsync, TimerDuration};
fn main() {
let rt = MiniAsync::new(TimerDuration::Real(Duration::from_millis(20)));
rt.add_task(async_main());
rt.run_until_empty();
}
async fn async_main() {
println!("Hello from async!")
}

27
src/lib.rs Normal file
View file

@ -0,0 +1,27 @@
pub mod rt;
use std::{cell::RefCell, ptr};
use rt::MiniAsync;
thread_local! {
static RUNTIME: RefCell<*const MiniAsync> = const { RefCell::new(ptr::null()) };
}
pub(crate) fn current_runtime(rt: &MiniAsync) {
RUNTIME.with_borrow_mut(|x| *x = rt as *const _);
}
pub(crate) fn exiting_runtime() {
RUNTIME.with_borrow_mut(|x| *x = ptr::null());
}
/// # Safety
/// The lifetime given out by this function is static but the underlying
/// struct is not, leading to use after free if this is not paid attention to.
pub unsafe fn get_runtime() -> &'static MiniAsync {
unsafe { &*RUNTIME.with_borrow(|x| *x) }
}
pub fn runtime(f: impl FnOnce(&MiniAsync)) {
f(unsafe { get_runtime() })
}

66
src/rt/mod.rs Normal file
View file

@ -0,0 +1,66 @@
mod waker;
use std::{
future::Future,
pin::Pin,
sync::Mutex,
task::{Context, Poll},
vec::Vec,
};
pub use microlock::timer::TimerDuration;
use microlock::Lock;
use crate::{current_runtime, exiting_runtime};
use self::waker::MicroWaker;
pub type Task<T> = Pin<Box<dyn Future<Output = T>>>;
pub struct MiniAsync {
tasks: Vec<Task<()>>,
tasks_to_add: Mutex<Vec<Task<()>>>,
waker: MicroWaker,
wake_attempt_delay: TimerDuration,
}
impl MiniAsync {
pub fn new(wake_attempt_delay: TimerDuration) -> Self {
Self {
tasks: Vec::new(),
tasks_to_add: Mutex::new(Vec::new()),
waker: MicroWaker::new(),
wake_attempt_delay,
}
}
pub fn add_boxed_task(&self, future: Pin<Box<impl Future<Output = ()> + 'static>>) {
self.tasks_to_add.lock().unwrap().push(future);
self.waker.lock.unlock();
}
pub fn add_task(&self, future: impl Future<Output = ()> + 'static) {
self.tasks_to_add.lock().unwrap().push(Box::pin(future));
self.waker.lock.unlock();
}
pub fn run_until_empty(mut self) {
current_runtime(&self);
let waker = self.waker.rust_waker();
let mut cx = Context::from_waker(&waker);
while !self.tasks.is_empty() {
let mut next_tasks = Vec::with_capacity(self.tasks.len());
for mut task in self.tasks {
match Future::poll(task.as_mut(), &mut cx) {
Poll::Ready(_) => drop(task),
Poll::Pending => next_tasks.push(task),
};
}
next_tasks.append(&mut self.tasks_to_add.lock().unwrap());
self.tasks = next_tasks;
self.waker.lock.wait_here_for(self.wake_attempt_delay);
self.waker.lock.try_lock();
}
exiting_runtime();
}
}

37
src/rt/waker.rs Normal file
View file

@ -0,0 +1,37 @@
use std::task::{RawWaker, RawWakerVTable, Waker};
use microlock::{Lock, TimedLock};
pub struct MicroWaker {
pub(crate) lock: TimedLock,
}
impl MicroWaker {
pub fn new() -> MicroWaker {
Self {
lock: TimedLock::locked(),
}
}
pub fn rust_waker(&self) -> Waker {
unsafe { Waker::from_raw(Self::clone(self as *const _ as _)) }
}
fn clone(me: *const ()) -> RawWaker {
RawWaker::new(
me,
&RawWakerVTable::new(Self::clone, Self::wake, Self::wake_by_ref, Self::drop),
)
}
unsafe fn wake(me: *const ()) {
let me = &*(me as *const Self);
me.lock.unlock();
}
unsafe fn wake_by_ref(me: *const ()) {
let me = &*(me as *const Self);
me.lock.unlock();
}
unsafe fn drop(_me: *const ()) {}
}