Skip to content

Commit

Permalink
Create context tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Feb 18, 2024
1 parent ae5ee40 commit 3ab0c84
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 22 deletions.
2 changes: 1 addition & 1 deletion examples/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use concoct::{
System,
};

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

Expand Down
15 changes: 10 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::{cell::RefCell, collections::VecDeque, rc::Rc, task::Waker};

use task::{Context, Task};
use std::{
cell::RefCell,
collections::{HashMap, VecDeque},
rc::Rc,
task::Waker,
};
use task::{Scope, Task};

pub mod task;

Expand All @@ -13,7 +17,7 @@ pub struct System<M, F, S> {
pub model: M,
make_task: F,
state: Option<S>,
cx: Context<M>,
cx: Scope<M>,
queue: Rc<RefCell<Queue<M>>>,
}

Expand All @@ -29,14 +33,15 @@ impl<M: 'static, F, S> System<M, F, S> {
make_task,
state: None,
queue: queue.clone(),
cx: Context {
cx: Scope {
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();
}
}),
contexts: RefCell::new(HashMap::new()),
},
}
}
Expand Down
45 changes: 45 additions & 0 deletions src/task/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use super::Task;
use std::{any::TypeId, marker::PhantomData, rc::Rc};

pub fn context<T: 'static>() -> Context<T> {
Context {
_marker: PhantomData,
}
}

pub struct Context<T> {
_marker: PhantomData<T>,
}

impl<M, T: 'static> Task<M> for Context<T> {
type Output = Rc<T>;

type State = ();

fn build(&mut self, cx: &super::Scope<M, ()>, _model: &mut M) -> (Self::Output, Self::State) {
let rc = cx
.contexts
.borrow()
.get(&TypeId::of::<T>())
.unwrap()
.clone();
let output = Rc::downcast(rc).unwrap();
(output, ())
}

fn rebuild(
&mut self,
cx: &super::Scope<M, ()>,
_model: &mut M,
_state: &mut Self::State,
) -> Self::Output {
let rc = cx
.contexts
.borrow()
.get(&TypeId::of::<T>())
.unwrap()
.clone();
let output = Rc::downcast(rc).unwrap();
output
}
}
4 changes: 2 additions & 2 deletions src/task/from_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ where

type State = ();

fn build(&mut self, _cx: &super::Context<M, ()>, model: &mut M) -> (Self::Output, Self::State) {
fn build(&mut self, _cx: &super::Scope<M, ()>, model: &mut M) -> (Self::Output, Self::State) {
((self.f)(model), ())
}

fn rebuild(
&mut self,
_cx: &super::Context<M, ()>,
_cx: &super::Scope<M, ()>,
model: &mut M,
_state: &mut Self::State,
) -> Self::Output {
Expand Down
28 changes: 17 additions & 11 deletions src/task/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
use std::any::{Any, TypeId};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

mod context;
pub use self::context::{context, Context};

mod from_fn;
pub use self::from_fn::{from_fn, FromFn};

mod provider;
pub use self::provider::{provider, Provider};

mod then;
pub use self::then::Then;

pub struct Context<M, A = ()> {
pub struct Scope<M, A = ()> {
pub(crate) waker: Rc<dyn Fn(Rc<dyn Fn(&mut M) -> Option<A>>)>,
pub(crate) contexts: RefCell<HashMap<TypeId, Rc<dyn Any>>>,
}

impl<M, A> Context<M, A> {
impl<M, A> Scope<M, A> {
pub fn update(&self, f: impl Fn(&mut M) -> Option<A> + 'static) {
(self.waker)(Rc::new(f))
}
Expand All @@ -21,14 +31,10 @@ pub trait Task<M, A = ()> {

type State;

fn build(&mut self, cx: &Context<M, A>, model: &mut M) -> (Self::Output, Self::State);
fn build(&mut self, cx: &Scope<M, A>, model: &mut M) -> (Self::Output, Self::State);

fn rebuild(
&mut self,
cx: &Context<M, A>,
model: &mut M,
state: &mut Self::State,
) -> Self::Output;
fn rebuild(&mut self, cx: &Scope<M, A>, model: &mut M, state: &mut Self::State)
-> Self::Output;

fn then<F, T>(self, f: F) -> Then<Self, F, T, M>
where
Expand All @@ -46,13 +52,13 @@ impl<M> Task<M> for () {

type State = ();

fn build(&mut self, _cx: &Context<M, ()>, _model: &mut M) -> (Self::Output, Self::State) {
fn build(&mut self, _cx: &Scope<M, ()>, _model: &mut M) -> (Self::Output, Self::State) {
((), ())
}

fn rebuild(
&mut self,
_cx: &Context<M, ()>,
_cx: &Scope<M, ()>,
_model: &mut M,
_state: &mut Self::State,
) -> Self::Output {
Expand Down
37 changes: 37 additions & 0 deletions src/task/provider.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use super::Task;
use std::{any::TypeId, rc::Rc};

pub fn provider<T: 'static>(value: T) -> Provider<T> {
Provider {
value: Rc::new(value),
}
}

pub struct Provider<T> {
value: Rc<T>,
}

impl<M, T: 'static> Task<M> for Provider<T> {
type Output = Rc<T>;

type State = ();

fn build(&mut self, cx: &super::Scope<M, ()>, _model: &mut M) -> (Self::Output, Self::State) {
cx.contexts
.borrow_mut()
.insert(TypeId::of::<T>(), self.value.clone());
(self.value.clone(), ())
}

fn rebuild(
&mut self,
cx: &super::Scope<M, ()>,
_model: &mut M,
_state: &mut Self::State,
) -> Self::Output {
cx.contexts
.borrow_mut()
.insert(TypeId::of::<T>(), self.value.clone());
self.value.clone()
}
}
6 changes: 3 additions & 3 deletions src/task/then.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Context, Task};
use super::{Scope, Task};
use std::marker::PhantomData;

pub struct Then<T1, F, T2, M> {
Expand Down Expand Up @@ -28,7 +28,7 @@ where

type State = (T1::State, T2::State);

fn build(&mut self, cx: &Context<M, ()>, model: &mut M) -> (Self::Output, Self::State) {
fn build(&mut self, cx: &Scope<M, ()>, model: &mut M) -> (Self::Output, Self::State) {
let (output, state) = self.task.build(cx, model);
let mut next = (self.f)(model, output);
let (next_output, next_state) = next.build(cx, model);
Expand All @@ -37,7 +37,7 @@ where

fn rebuild(
&mut self,
cx: &Context<M, ()>,
cx: &Scope<M, ()>,
model: &mut M,
state: &mut Self::State,
) -> Self::Output {
Expand Down

0 comments on commit 3ab0c84

Please sign in to comment.