Skip to content

Commit

Permalink
Rework Mountable so that we can mount other things later
Browse files Browse the repository at this point in the history
We will need something higher level than the Chain but lower level than the synthesizer
to do everything we want to do. Tentatively I am calling this the algorithm.  In order
to make that work we need enough flexibility in these admittedly confusing traits to let algorithms also mount.
  • Loading branch information
ahicks92 committed Dec 31, 2024
1 parent d54f7e4 commit 2f5ed51
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 47 deletions.
19 changes: 0 additions & 19 deletions crates/synthizer/src/core_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,25 +132,6 @@ where
}
}

pub trait Generator: for<'a> Signal<Input<'a> = ()> {}
impl<T> Generator for T where T: for<'a> Signal<Input<'a> = ()> {}

/// A mountable signal has no inputs and no outputs, and its state and parameters are 'static.
pub trait Mountable
where
Self: Generator + Send + Sync + 'static,
Self: for<'a> Signal<Output<'a> = ()> + Generator,
SignalState<Self>: Send + Sync + 'static,
{
}

impl<T> Mountable for T
where
T: Generator + for<'a> Signal<Output<'a> = ()> + Send + Sync + 'static,
SignalState<T>: Send + Sync + 'static,
{
}

// Workarounds for https://github.com/rust-lang/rust/issues/38078: rustc is not always able to determine when a type
// isn't ambiguous, or at the very least it doesn't tell us what the options are, so we use this instead.
pub(crate) type IntoSignalOutput<'a, S> = <<S as IntoSignal>::Signal as Signal>::Output<'a>;
Expand Down
95 changes: 89 additions & 6 deletions crates/synthizer/src/mount_point.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#![allow(private_interfaces)]
use std::any::Any;
use std::sync::Arc;

use crate::config;
use crate::context::*;
use crate::core_traits::*;
use crate::error::Result;
use crate::synthesizer::SynthesizerState;

use crate::unique_id::UniqueId;
use crate::Chain;

pub(crate) struct MountPoint<S: Mountable>
pub(crate) struct MountPoint<S: ExecutableMount>
where
S::State: Send + Sync + 'static,
{
pub(crate) signal: S,
pub(crate) handler: S,
pub(crate) state: S::State,
}

Expand All @@ -23,16 +26,59 @@ pub(crate) trait ErasedMountPoint: Send + Sync + 'static {
mount_id: &UniqueId,
shared_ctx: &FixedSignalExecutionContext,
);

fn trace_slots(&self, tracer: &mut dyn FnMut(UniqueId, Arc<dyn Any + Send + Sync + 'static>));
}

pub mod sealed {
use super::*;

pub trait ExecutableMount: Send + Sync + 'static + Sized {
type State: Send + Sync + 'static;

fn trace_slots(
state: &Self::State,
inserter: &mut dyn FnMut(UniqueId, Arc<dyn Any + Send + Sync + 'static>),
);

fn run(
mount: &mut MountPoint<Self>,
state: &Arc<SynthesizerState>,
mount_id: &UniqueId,
shared_ctx: &FixedSignalExecutionContext,
);
}

pub trait Mountable {
fn into_mount(
self,
batch: &mut crate::synthesizer::Batch,
) -> Result<Box<dyn ErasedMountPoint>>;
}
}

impl<S: Mountable> ErasedMountPoint for MountPoint<S> {
pub(crate) use sealed::*;

impl<S> ExecutableMount for S
where
for<'il, 'ol> S: Signal<Input<'il> = (), Output<'ol> = ()>,
{
type State = SignalState<S>;

fn trace_slots(
state: &Self::State,
mut inserter: &mut dyn FnMut(UniqueId, Arc<dyn Any + Send + Sync + 'static>),
) {
Self::trace_slots(state, &mut inserter);
}

fn run(
&mut self,
mount: &mut MountPoint<Self>,
_state: &Arc<SynthesizerState>,
_mount_id: &UniqueId,
shared_ctx: &FixedSignalExecutionContext,
) {
let sig_state = &mut self.state;
let sig_state = &mut mount.state;

let ctx = SignalExecutionContext { fixed: shared_ctx };

Expand All @@ -44,3 +90,40 @@ impl<S: Mountable> ErasedMountPoint for MountPoint<S> {
);
}
}

impl<S: ExecutableMount> ErasedMountPoint for MountPoint<S> {
fn run(
&mut self,
state: &Arc<SynthesizerState>,
mount_id: &UniqueId,
shared_ctx: &FixedSignalExecutionContext,
) {
S::run(self, state, mount_id, shared_ctx);
}

fn trace_slots(
&self,
mut tracer: &mut dyn FnMut(UniqueId, Arc<dyn Any + Send + Sync + 'static>),
) {
<S as ExecutableMount>::trace_slots(&self.state, &mut tracer);
}
}

impl<S: IntoSignal> Mountable for Chain<S>
where
for<'il, 'ol> S::Signal: Signal<Input<'il> = (), Output<'ol> = ()>,
{
fn into_mount(
self,
_batch: &mut crate::synthesizer::Batch,
) -> Result<Box<dyn ErasedMountPoint>> {
let ready = self.into_signal()?;

let mp = MountPoint {
handler: ready.signal,
state: ready.state,
};

Ok(Box::new(mp))
}
}
31 changes: 9 additions & 22 deletions crates/synthizer/src/synthesizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ use std::any::Any;
use std::marker::PhantomData as PD;
use std::sync::Arc;

use atomic_refcell::AtomicRefCell;
use rpds::{HashTrieMapSync, VectorSync};

use crate::chain::Chain;
use crate::config;
use crate::core_traits::*;
use crate::error::{Error, Result};
use crate::mount_point::ErasedMountPoint;
use crate::signals::{Slot, SlotMap, SlotUpdateContext, SlotValueContainer};
use crate::unique_id::UniqueId;
use atomic_refcell::AtomicRefCell;
use rpds::{HashTrieMapSync, VectorSync};

type SynthMap<K, V> = HashTrieMapSync<K, V>;
type SynthVec<T> = VectorSync<T>;
Expand Down Expand Up @@ -202,33 +199,23 @@ impl Batch<'_> {
}
}

pub fn mount<S: IntoSignal>(&mut self, chain: Chain<S>) -> Result<Handle>
where
S::Signal: Mountable,
SignalState<S::Signal>: Send + Sync + 'static,
{
pub fn mount<M: crate::mount_point::Mountable>(&mut self, new_mount: M) -> Result<Handle> {
let object_id = UniqueId::new();
let pending_drop = MarkDropped::new();
let mount = new_mount.into_mount(self)?;

let ready = chain.into_signal()?;
let pending_drop = MarkDropped::new();

let mut slots: SlotMap<UniqueId, Arc<dyn Any + Send + Sync + 'static>> = Default::default();
let mut slots = SlotMap::new_sync();

S::Signal::trace_slots(&ready.state, &mut |id, s| {
slots.insert_mut(id, s);
mount.trace_slots(&mut |id, val| {
slots.insert_mut(id, val);
});

let mp = crate::mount_point::MountPoint {
signal: ready.signal,
state: ready.state,
};

let inserting = MountContainer {
erased_mount: Arc::new(AtomicRefCell::new(Box::new(mp))),
erased_mount: Arc::new(AtomicRefCell::new(mount)),
pending_drop: pending_drop.0.clone(),
slots,
};

self.new_state.mounts.insert_mut(object_id, inserting);

Ok(Handle {
Expand Down

0 comments on commit 2f5ed51

Please sign in to comment.