Skip to content

Commit

Permalink
add G: Gen<T> to ViewMut
Browse files Browse the repository at this point in the history
  • Loading branch information
schell committed Dec 17, 2023
1 parent dc9ec10 commit fa2a922
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 16 deletions.
2 changes: 1 addition & 1 deletion crates/moongraph/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "moongraph"
version = "0.3.7"
version = "0.3.8"
edition = "2021"
description = "Schedules and runs DAGs accessing shared resources. 🌙"
repository = "https://github.com/schell/moongraph"
Expand Down
59 changes: 44 additions & 15 deletions crates/moongraph/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ impl<T> Gen<T> for NoDefault {

/// Immutably borrowed resource that _may_ be created by default.
///
/// [`View`] and [`ViewMut`] are the main way node functions interact with resources.
/// Node functions wrap their parameters in [`View`], [`ViewMut`] or [`Move`].
///
/// `View` has two type parameters:
/// * `T` - The type of the resource.
Expand Down Expand Up @@ -467,7 +467,8 @@ impl<T: Any + Send + Sync, G: Gen<T>> Edges for View<T, G> {
let t = G::generate().context(MissingSnafu {
name: std::any::type_name::<T>(),
})?;
// UNWRAP: safe because we know this type was missing
// UNWRAP: safe because we know this type was missing, and no other type
// is stored with this type's type id.
let _ = resources.insert_value(t).unwrap();
log::trace!("generated missing {}", std::any::type_name::<T>());
// UNWRAP: safe because we just inserted
Expand All @@ -488,13 +489,33 @@ impl<T: std::fmt::Display + Any + Send + Sync, G: Gen<T>> std::fmt::Display for
}
}

/// Specifies a graph edge/resource that can be "written" to by a node.
pub struct ViewMut<T> {
/// A mutably borrowed resource that may be created by default.
///
/// Node functions wrap their parameters in [`View`], [`ViewMut`] or [`Move`].
///
/// `ViewMut` has two type parameters:
/// * `T` - The type of the resource.
/// * `G` - The method by which the resource can be generated if it doesn't
/// already exist. By default this is [`SomeDefault`], which denotes creating
/// the resource using its default implementation. Another option is
/// [`NoDefault`] which fails to generate the resource.
///
/// ```rust
/// use moongraph::*;
///
/// let mut graph = Graph::default();
/// let default_number = graph.visit(|u: ViewMut<usize>| { *u }).map_err(|e| e.to_string());
/// assert_eq!(Ok(0), default_number);
///
/// let no_number = graph.visit(|f: ViewMut<f32, NoDefault>| *f);
/// assert!(no_number.is_err());
/// ```
pub struct ViewMut<T, G: Gen<T> = SomeDefault> {
inner: LoanMut,
_phantom: PhantomData<T>,
_phantom: PhantomData<(T, G)>,
}

impl<T: Any + Send + Sync> Deref for ViewMut<T> {
impl<T: Any + Send + Sync, G: Gen<T>> Deref for ViewMut<T, G> {
type Target = T;

fn deref(&self) -> &Self::Target {
Expand All @@ -503,34 +524,42 @@ impl<T: Any + Send + Sync> Deref for ViewMut<T> {
}
}

impl<T: Any + Send + Sync> DerefMut for ViewMut<T> {
impl<T: Any + Send + Sync, G: Gen<T>> DerefMut for ViewMut<T, G> {
fn deref_mut(&mut self) -> &mut Self::Target {
// UNWRAP: safe because it was constructed with `T`
self.inner.downcast_mut().unwrap()
}
}

impl<'a, T: Any + Send + Sync> Edges for ViewMut<T> {
impl<'a, T: Any + Send + Sync, G: Gen<T>> Edges for ViewMut<T, G> {
fn writes() -> Vec<TypeKey> {
vec![TypeKey::new::<T>()]
}

fn construct(resources: &mut TypeMap) -> Result<Self, GraphError> {
let key = TypeKey::new::<T>();
let inner = resources
.loan_mut(key)
.context(ResourceSnafu)?
.context(MissingSnafu {
name: std::any::type_name::<T>(),
})?;
let inner = match resources.loan_mut(key).context(ResourceSnafu)? {
Some(inner) => inner,
None => {
let t = G::generate().context(MissingSnafu {
name: std::any::type_name::<T>(),
})?;
// UNWRAP: safe because we know this type was missing, and no other type
// is stored with this type's type id.
let _ = resources.insert_value(t).unwrap();
log::trace!("generated missing {}", std::any::type_name::<T>());
// UNWRAP: safe because we just inserted
resources.loan_mut(key).unwrap().unwrap()
}
};
Ok(ViewMut {
inner,
_phantom: PhantomData,
})
}
}

impl<T: std::fmt::Display + Any + Send + Sync> std::fmt::Display for ViewMut<T> {
impl<T: std::fmt::Display + Any + Send + Sync, G: Gen<T>> std::fmt::Display for ViewMut<T, G> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let t: &T = self.inner.downcast_ref().unwrap();
t.fmt(f)
Expand Down
9 changes: 9 additions & 0 deletions crates/moongraph/src/tutorial_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,16 @@
/// ```rust
/// use moongraph::*;
///
/// #[derive(Default)]
/// pub struct Position(f32, f32);
///
/// #[derive(Default)]
/// pub struct Velocity(f32, f32);
///
/// #[derive(Default)]
/// pub struct Acceleration(f32, f32);
///
/// #[derive(Default)]
/// pub struct BankAccount {
/// interest_rate: f32,
/// balance: f32,
Expand Down Expand Up @@ -260,6 +267,8 @@
///
/// Notice how the returned schedule shows that `add_velocity` and `compound_interest` can run together in parallel. We call this a "batch". It's possible to run all nodes in a batch at the same time because none of their borrows conflict and there are no explicit ordering constraints between them.
///
///
///
/// ## Conclusion
/// Hopefully by this point you have a better idea what `moongraph` is about and how to use it.
/// For more info please look at the module and type level documentation.
Expand Down

0 comments on commit fa2a922

Please sign in to comment.