Simplify Synchronicity trait

This commit is contained in:
Shadowfacts 2024-11-02 23:56:51 -04:00
parent 6d1e505590
commit 36bcbe3c9c
3 changed files with 18 additions and 37 deletions

View File

@ -59,7 +59,7 @@ use node::{ErasedNode, NodeValue};
use petgraph::visit::{IntoEdgeReferences, NodeIndexable};
use petgraph::{stable_graph::StableDiGraph, visit::EdgeRef};
use rule::{AsyncRule, Input, InputVisitor, Rule};
use std::cell::{Cell, Ref, RefCell};
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::collections::VecDeque;
use std::ops::{Deref, DerefMut};

View File

@ -10,7 +10,7 @@ pub(crate) struct ErasedNode<Synch: Synchronicity> {
is_valid: Box<dyn Fn(&Box<dyn Any>) -> bool>,
invalidate: Box<dyn Fn(&mut Box<dyn Any>) -> ()>,
visit_inputs: Box<dyn Fn(&Box<dyn Any>, &mut dyn FnMut(NodeId) -> ()) -> ()>,
update: Synch::UpdateFn,
update: Box<dyn for<'a> Fn(&'a mut Box<dyn Any>) -> Synch::UpdateResult<'a>>,
}
impl<S: Synchronicity> ErasedNode<S> {
@ -32,7 +32,10 @@ impl<S: Synchronicity> ErasedNode<S> {
let x = any.downcast_ref::<Box<dyn Node<V, S>>>().unwrap();
x.visit_inputs(visitor);
}),
update: S::make_update_fn::<V>(),
update: Box::new(|any| {
let x = any.downcast_mut::<Box<dyn Node<V, S>>>().unwrap();
x.update()
}),
}
}
@ -164,7 +167,7 @@ impl<V: NodeValue, S: Synchronicity> Node<V, S> for InvalidatableConstNode<V, S>
self.valid = true;
// This node is only invalidate when node_value_eq between the old/new value is false,
// so it is always the case that the update method has changed the value.
S::make_update_result(true)
S::make_update_result(true, crate::synchronicity::private::Token)
}
fn value_rc(&self) -> &Rc<RefCell<Option<V>>> {
@ -222,7 +225,7 @@ impl<R: Rule, S: Synchronicity> Node<R::Output, S> for RuleNode<R, R::Output, S>
*value = Some(new_value);
}
S::make_update_result(value_changed)
S::make_update_result(value_changed, crate::synchronicity::private::Token)
}
fn value_rc(&self) -> &Rc<RefCell<Option<R::Output>>> {

View File

@ -4,41 +4,31 @@
//! The [`Synchronicity`] trait is sealed to outside implementors, and you generally do not need to refer
//! directly to the [`Synchronous`] or [`Asynchronous`] types.
use crate::node::{Node, NodeValue};
use std::any::Any;
use std::future::Future;
use std::pin::Pin;
mod private {
pub(crate) mod private {
pub trait Sealed {}
impl Sealed for super::Synchronous {}
impl Sealed for super::Asynchronous {}
impl Sealed for bool {}
impl<'a> Sealed for <super::Asynchronous as super::Synchronicity>::UpdateResult<'a> {}
pub struct Token;
}
pub trait Synchronicity: private::Sealed + 'static {
// TODO: do we need the associated type? can this just be a method update_node(Box<dyn Node<V>>)?
type UpdateFn;
fn make_update_fn<V: NodeValue>() -> Self::UpdateFn;
type UpdateResult<'a>;
fn make_update_result<'a>(result: bool) -> Self::UpdateResult<'a>;
type UpdateResult<'a>: private::Sealed;
// Necessary for synchronous nodes that can be part of an async graph to return the
// appropriate result based on the type of graph they're in.
fn make_update_result<'a>(result: bool, _: private::Token) -> Self::UpdateResult<'a>;
}
pub struct Synchronous;
impl Synchronicity for Synchronous {
type UpdateFn = Box<dyn Fn(&mut Box<dyn Any>) -> bool>;
fn make_update_fn<V: NodeValue>() -> Self::UpdateFn {
Box::new(|any| {
let x = any.downcast_mut::<Box<dyn Node<V, Self>>>().unwrap();
x.update()
})
}
type UpdateResult<'a> = bool;
fn make_update_result<'a>(result: bool) -> Self::UpdateResult<'a> {
fn make_update_result<'a>(result: bool, _: private::Token) -> Self::UpdateResult<'a> {
result
}
}
@ -46,21 +36,9 @@ impl Synchronicity for Synchronous {
pub struct Asynchronous;
impl Synchronicity for Asynchronous {
type UpdateFn =
Box<dyn for<'a> Fn(&'a mut Box<dyn Any>) -> Pin<Box<dyn Future<Output = bool> + 'a>>>;
fn make_update_fn<V: NodeValue>() -> Self::UpdateFn {
Box::new(|any| {
Box::pin({
let x = any.downcast_mut::<Box<dyn Node<V, Self>>>().unwrap();
x.update()
})
})
}
type UpdateResult<'a> = Pin<Box<dyn Future<Output = bool> + 'a>>;
fn make_update_result<'a>(result: bool) -> Self::UpdateResult<'a> {
fn make_update_result<'a>(result: bool, _: private::Token) -> Self::UpdateResult<'a> {
Box::pin(std::future::ready(result))
}
}