Skip to content

Commit

Permalink
Create System struct and basic example
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Feb 18, 2024
1 parent 3184f27 commit ae5ee40
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 2 deletions.
14 changes: 14 additions & 0 deletions examples/app.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use concoct::{
task::{self, Task},
System,
};

fn app(count: &mut i32) -> impl Task<i32> {
task::from_fn(|_| dbg!("Hello World!"))
}

fn main() {
let mut system = System::new(0, app);
system.build();
system.rebuild();
}
80 changes: 80 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,81 @@
use std::{cell::RefCell, collections::VecDeque, rc::Rc, task::Waker};

use task::{Context, Task};

pub mod task;

struct Queue<M> {
events: VecDeque<Rc<dyn Fn(&mut M) -> Option<()>>>,
waker: Option<Waker>,
}

pub struct System<M, F, S> {
pub model: M,
make_task: F,
state: Option<S>,
cx: Context<M>,
queue: Rc<RefCell<Queue<M>>>,
}

impl<M: 'static, F, S> System<M, F, S> {
pub fn new(model: M, make_task: F) -> Self {
let queue = Rc::new(RefCell::new(Queue {
events: VecDeque::new(),
waker: None,
}));

Self {
model,
make_task,
state: None,
queue: queue.clone(),
cx: Context {
waker: Rc::new(move |f| {
let mut q = queue.borrow_mut();
q.events.push_back(f);
if let Some(waker) = q.waker.take() {
waker.wake();
}
}),
},
}
}

pub fn build<T>(&mut self) -> T::Output
where
F: FnMut(&mut M) -> T,
T: Task<M, State = S>,
{
let mut task = (self.make_task)(&mut self.model);
let (output, state) = task.build(&self.cx, &mut self.model);
self.state = Some(state);
output
}

pub fn rebuild<T>(&mut self) -> T::Output
where
F: FnMut(&mut M) -> T,
T: Task<M, State = S>,
{
let mut task = (self.make_task)(&mut self.model);
task.rebuild(&self.cx, &mut self.model, self.state.as_mut().unwrap())
}

pub async fn update(&mut self) {
futures::future::poll_fn(|cx| {
let mut queue = self.queue.borrow_mut();
let mut is_ready = false;
while let Some(update) = queue.events.pop_front() {
update(&mut self.model);
is_ready = true;
}
if is_ready {
std::task::Poll::Ready(())
} else {
queue.waker = Some(cx.waker().clone());
std::task::Poll::Pending
}
})
.await
}
}
4 changes: 2 additions & 2 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pub use self::from_fn::{from_fn, FromFn};
mod then;
pub use self::then::Then;

pub struct Context<M, A> {
waker: Rc<dyn Fn(Rc<dyn Fn(&mut M) -> Option<A>>)>,
pub struct Context<M, A = ()> {
pub(crate) waker: Rc<dyn Fn(Rc<dyn Fn(&mut M) -> Option<A>>)>,
}

impl<M, A> Context<M, A> {
Expand Down

0 comments on commit ae5ee40

Please sign in to comment.