Add GraphBuilder::add_async_value
This commit is contained in:
parent
88dfef75fd
commit
a556b14188
@ -1,4 +1,6 @@
|
|||||||
use crate::node::{AsyncRuleNode, ConstNode, InvalidatableConstNode, Node, NodeValue, RuleNode};
|
use crate::node::{
|
||||||
|
AsyncConstNode, AsyncRuleNode, ConstNode, InvalidatableConstNode, Node, NodeValue, RuleNode,
|
||||||
|
};
|
||||||
use crate::rule::{AsyncRule, Rule};
|
use crate::rule::{AsyncRule, Rule};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -6,6 +8,7 @@ use crate::{
|
|||||||
Synchronous, ValueInvalidationSignal,
|
Synchronous, ValueInvalidationSignal,
|
||||||
};
|
};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::future::Future;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
/// Builds a [`Graph`].
|
/// Builds a [`Graph`].
|
||||||
@ -228,7 +231,19 @@ impl<O: 'static> GraphBuilder<O, Asynchronous> {
|
|||||||
self.output = Some(input);
|
self.output = Some(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add_async_value?
|
/// Adds a constant node whose value is computed by the given function to the graph.
|
||||||
|
///
|
||||||
|
/// The function is not called until the node is evaluated by the graph.
|
||||||
|
///
|
||||||
|
/// Returns an [`Input`] representing the newly-added node, which can be used to construct rules.
|
||||||
|
pub fn add_async_value<V, P, F>(&mut self, value_provider: P) -> Input<V>
|
||||||
|
where
|
||||||
|
V: NodeValue,
|
||||||
|
P: FnOnce() -> F + 'static,
|
||||||
|
F: Future<Output = V> + 'static,
|
||||||
|
{
|
||||||
|
self.add_node(AsyncConstNode::new(value_provider))
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a node whose value is produced using the given rule to the graph.
|
/// Adds a node whose value is produced using the given rule to the graph.
|
||||||
///
|
///
|
||||||
|
@ -627,4 +627,14 @@ mod tests {
|
|||||||
assert!(!graph.is_output_valid());
|
assert!(!graph.is_output_valid());
|
||||||
assert_eq!(*graph.evaluate(), 43);
|
assert_eq!(*graph.evaluate(), 43);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn async_value() {
|
||||||
|
let mut builder = GraphBuilder::new_async();
|
||||||
|
let a = builder.add_async_value(|| async { 42 });
|
||||||
|
let b = builder.add_value(1);
|
||||||
|
builder.set_output(Add(a, b));
|
||||||
|
let mut graph = builder.build().unwrap();
|
||||||
|
assert_eq!(*graph.evaluate_async().await, 43);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ use crate::synchronicity::{Asynchronous, Synchronicity};
|
|||||||
use crate::{AsyncRule, Input, InputVisitor, NodeId, Rule, Synchronous};
|
use crate::{AsyncRule, Input, InputVisitor, NodeId, Rule, Synchronous};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use std::future::Future;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub(crate) struct ErasedNode<Synch: Synchronicity> {
|
pub(crate) struct ErasedNode<Synch: Synchronicity> {
|
||||||
@ -229,6 +230,52 @@ impl<R: Rule, S: Synchronicity> Node<R::Output, S> for RuleNode<R, R::Output, S>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AsyncConstNode<V, P: FnOnce() -> F, F: Future<Output = V>> {
|
||||||
|
provider: Option<P>,
|
||||||
|
value: Rc<RefCell<Option<V>>>,
|
||||||
|
valid: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, P: FnOnce() -> F, F: Future<Output = V>> AsyncConstNode<V, P, F> {
|
||||||
|
pub(crate) fn new(provider: P) -> Self {
|
||||||
|
Self {
|
||||||
|
provider: Some(provider),
|
||||||
|
value: Rc::new(RefCell::new(None)),
|
||||||
|
valid: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn do_update(&mut self) -> bool {
|
||||||
|
self.valid = true;
|
||||||
|
let mut provider = None;
|
||||||
|
std::mem::swap(&mut self.provider, &mut provider);
|
||||||
|
*self.value.borrow_mut() = Some(provider.unwrap()().await);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V: NodeValue, P: FnOnce() -> F, F: Future<Output = V>> Node<V, Asynchronous>
|
||||||
|
for AsyncConstNode<V, P, F>
|
||||||
|
{
|
||||||
|
fn is_valid(&self) -> bool {
|
||||||
|
self.valid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate(&mut self) {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_inputs(&self, _visitor: &mut dyn FnMut(NodeId) -> ()) {}
|
||||||
|
|
||||||
|
fn update(&mut self) -> <Asynchronous as Synchronicity>::UpdateResult<'_> {
|
||||||
|
Box::pin(self.do_update())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_rc(&self) -> &Rc<RefCell<Option<V>>> {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct AsyncRuleNode<R, V> {
|
pub(crate) struct AsyncRuleNode<R, V> {
|
||||||
rule: R,
|
rule: R,
|
||||||
value: Rc<RefCell<Option<V>>>,
|
value: Rc<RefCell<Option<V>>>,
|
||||||
@ -243,6 +290,22 @@ impl<R: AsyncRule> AsyncRuleNode<R, R::Output> {
|
|||||||
valid: false,
|
valid: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn do_update(&mut self) -> bool {
|
||||||
|
self.valid = true;
|
||||||
|
|
||||||
|
let new_value = self.rule.evaluate().await;
|
||||||
|
let mut value = self.value.borrow_mut();
|
||||||
|
let value_changed = value
|
||||||
|
.as_ref()
|
||||||
|
.map_or(true, |v| !v.node_value_eq(&new_value));
|
||||||
|
|
||||||
|
if value_changed {
|
||||||
|
*value = Some(new_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_changed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: AsyncRule> Node<R::Output, Asynchronous> for AsyncRuleNode<R, R::Output> {
|
impl<R: AsyncRule> Node<R::Output, Asynchronous> for AsyncRuleNode<R, R::Output> {
|
||||||
@ -272,21 +335,3 @@ impl<R: AsyncRule> Node<R::Output, Asynchronous> for AsyncRuleNode<R, R::Output>
|
|||||||
&self.value
|
&self.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: AsyncRule> AsyncRuleNode<R, R::Output> {
|
|
||||||
async fn do_update(&mut self) -> bool {
|
|
||||||
self.valid = true;
|
|
||||||
|
|
||||||
let new_value = self.rule.evaluate().await;
|
|
||||||
let mut value = self.value.borrow_mut();
|
|
||||||
let value_changed = value
|
|
||||||
.as_ref()
|
|
||||||
.map_or(true, |v| !v.node_value_eq(&new_value));
|
|
||||||
|
|
||||||
if value_changed {
|
|
||||||
*value = Some(new_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
value_changed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user