1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
//! Common code used between different engines. //! //! Unless you're implementing your own generic `AnchorInner`s or your own execution engine, //! you should never need to import things from here. `singlethread` should re-export anything //! you need to use `anchors`! use std::marker::PhantomData; use std::panic::Location; mod ext; pub use ext::{AnchorExt, AnchorSplit}; mod constant; mod var; pub use constant::Constant; pub use var::{Var, VarSetter}; /// Indicates whether a value is ready for reading, and if it is, whether it's changed /// since the last read. #[derive(Debug, PartialEq, Eq)] pub enum Poll { /// Indicates the polled value is ready for reading. Either this is the first read, /// or the value has changed since the last read. Updated, /// Indicates the polled value is ready for reading. This is not the first read, and /// the value is unchanged since the previous read. Unchanged, /// Indicates the polled value is not ready for reading, but has been queued for recalculation. /// The output value will eventually switch to Updated or Unchanged. Pending, } /// The main struct of the Anchors library. Represents a single value on the recomputation graph. /// /// This doesn't contain the particular Anchor implementation directly, but instead contains an /// engine-specific `AnchorHandle` which allows the recalculation engine to identify which /// internal recomputation graph node this corresponds to. You should rarely create Anchors yourself; /// instead use one of the built-in functions like `Var::new` to create one, or create derivative Anchors /// with one of the `AnchorExt` methods. pub struct Anchor<O, E: Engine + ?Sized> { data: E::AnchorHandle, phantom: PhantomData<O>, } impl<O, E: Engine> Anchor<O, E> { pub fn new(data: E::AnchorHandle) -> Self { Self { data, phantom: PhantomData, } } /// Returns the immutable, copyable, hashable, comparable engine-specific ID for this Anchor. pub fn token(&self) -> <E::AnchorHandle as AnchorHandle>::Token { self.data.token() } } impl<O, E: Engine> Clone for Anchor<O, E> { fn clone(&self) -> Self { Self { data: self.data.clone(), phantom: PhantomData, } } } impl<O, E: Engine> PartialEq for Anchor<O, E> { fn eq(&self, other: &Self) -> bool { self.token() == other.token() } } impl<O, E: Engine> Eq for Anchor<O, E> {} /// A reference to a particular `AnchorInner`. Each engine implements its own. pub trait AnchorHandle: Sized + Clone { type Token: Sized + Clone + Copy + PartialEq + Eq + std::hash::Hash; /// Returns a Copyable, comparable, hashable ID corresponding to this AnchorHandle. /// Some engines may garbage collect an AnchorInner when no more AnchorHandles pointing /// to it exist, which means it's possible to have a Token pointing to a since-deleted /// Anchor. fn token(&self) -> Self::Token; } /// The core engine trait implemented by each recalculation engine. Allows mounting an `AnchorInner` /// into an actual `Anchor`, although this mounting should usually be done by each `AnchorInner` /// implementation directly. pub trait Engine: 'static { type AnchorHandle: AnchorHandle; type DirtyHandle: DirtyHandle; fn mount<I: AnchorInner<Self> + 'static>(inner: I) -> Anchor<I::Output, Self>; } /// Allows a node with non-Anchors inputs to manually mark itself as dirty. Each engine implements its own. pub trait DirtyHandle { /// Indicates that the Anchor associated with this `DirtyHandle` may have a changed its output, and should /// be repolled. fn mark_dirty(&self); } /// The context passed to an `AnchorInner` when its `output` method is called. pub trait OutputContext<'eng> { type Engine: Engine + ?Sized; /// If another Anchor during polling indicated its value was ready, the previously /// calculated value can be accessed with this method. Its implementation is virtually /// identical to `UpdateContext`'s `get`. This is mostly used by AnchorInner implementations /// that want to return a reference to some other Anchor's output without cloning. fn get<'out, O: 'static>(&self, anchor: &Anchor<O, Self::Engine>) -> &'out O where 'eng: 'out; } /// The context passed to an `AnchorInner` when its `poll_updated` method is called. pub trait UpdateContext { type Engine: Engine + ?Sized; /// If `request` indicates another Anchor's value is ready, the previously /// calculated value can be accessed with this method. fn get<'out, 'slf, O: 'static>(&'slf self, anchor: &Anchor<O, Self::Engine>) -> &'out O where 'slf: 'out; /// If `anchor`'s output is ready, indicates whether the output has changed since this `AnchorInner` /// last called `request` on it. If `anchor`'s output is not ready, it is queued for recalculation and /// this returns Poll::Pending. /// /// `necessary` is a bit that indicates if we are necessary, `anchor` should be marked as necessary /// as well. If you don't know what this bit should be set to, you probably want a value of `true`. fn request<'out, O: 'static>( &mut self, anchor: &Anchor<O, Self::Engine>, necessary: bool, ) -> Poll; /// If `anchor` was previously passed to `request` and you no longer care about its output, you can /// pass it to `unrequest` so the engine will stop calling your `dirty` method when `anchor` changes. /// If `self` is necessary, this is also critical for ensuring `anchor` is no longer marked as necessary. fn unrequest<'out, O: 'static>(&mut self, anchor: &Anchor<O, Self::Engine>); /// Returns a new dirty handle, used for marking that `self`'s output may have changed through some /// non incremental means. For instance, perhaps this `AnchorInner`s value represents the current time, or /// it's a `Var` that has a setter function. fn dirty_handle(&mut self) -> <Self::Engine as Engine>::DirtyHandle; } /// The engine-agnostic implementation of each type of Anchor. You likely don't need to implement your own /// `AnchorInner`; instead use one of the built-in implementations. pub trait AnchorInner<E: Engine + ?Sized> { type Output; /// Called by the engine to indicate some input may have changed. /// If this `AnchorInner` still cares about `child`'s value, it should re-request /// it next time `poll_updated` is called. fn dirty(&mut self, child: &<E::AnchorHandle as AnchorHandle>::Token); /// Called by the engine when it wants to know if this value has changed or /// not. If some requested value from `ctx` is `Pending`, this method should /// return `Poll::Pending`; otherwise it must finish recalculation and report /// either `Poll::Updated` or `Poll::Unchanged`. fn poll_updated<G: UpdateContext<Engine = E>>(&mut self, ctx: &mut G) -> Poll; /// Called by the engine to get the current output value of this `AnchorInner`. This /// is *only* called after this `AnchorInner` reported in the return value from /// `poll_updated` the value was ready. If `dirty` is called, this function will not /// be called until `poll_updated` returns a non-Pending value. fn output<'slf, 'out, G: OutputContext<'out, Engine = E>>( &'slf self, ctx: &mut G, ) -> &'out Self::Output where 'slf: 'out; /// An optional function to report the track_caller-derived callsite where /// this Anchor was created. Useful for debugging purposes. fn debug_location(&self) -> Option<(&'static str, &'static Location<'static>)> { None } }