💹 Remove unnecessary `Rc` in `FullTile`

main
Shad Amethyst 2 years ago
parent 66ccc1dd30
commit dd2de9ee14
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -1,5 +1,4 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc;
use super::*; use super::*;
/** An `UpdateContext` is created for every tile update during the "update" phase, /** An `UpdateContext` is created for every tile update during the "update" phase,
@ -48,7 +47,7 @@ impl Tile for MyTile {
ctx.next_state(); // Become dormant ctx.next_state(); // Become dormant
} }
# #
# fn transmit<'b>(&'b self, signal: std::rc::Rc<Signal>, ctx: TransmitContext<'b>) {} # fn transmit<'b>(&'b self, signal: Signal, ctx: TransmitContext<'b>) {}
} }
``` ```
@ -90,7 +89,7 @@ impl<'a> UpdateContext<'a> {
/// Returns the [signal](crate::FullTile::signal) of the currently updated tile. /// Returns the [signal](crate::FullTile::signal) of the currently updated tile.
#[inline] #[inline]
pub fn signal<'b>(&'b self) -> Option<&'b Rc<Signal>> where 'a: 'b { pub fn signal<'b>(&'b self) -> Option<&'b Signal> where 'a: 'b {
let pane = unsafe { self.pane() }; let pane = unsafe { self.pane() };
// SAFETY: `pane[position].signal` is not borrowed mutably // SAFETY: `pane[position].signal` is not borrowed mutably
@ -170,7 +169,7 @@ pub struct TransmitContext<'a> {
} }
impl<'a> TransmitContext<'a> { impl<'a> TransmitContext<'a> {
pub(crate) fn new(pane: &'a mut Pane, position: (usize, usize)) -> Option<(Self, &'a AnyTile, Rc<Signal>)> { pub(crate) fn new(pane: &'a mut Pane, position: (usize, usize)) -> Option<(Self, &'a AnyTile, Signal)> {
let ptr: *mut Pane = &mut *pane; let ptr: *mut Pane = &mut *pane;
// SAFETY: no mutable accesses to `∀x, pane[x].cell` are made by `TransmitContext` // SAFETY: no mutable accesses to `∀x, pane[x].cell` are made by `TransmitContext`
let tile: &AnyTile = unsafe { let tile: &AnyTile = unsafe {
@ -240,22 +239,18 @@ impl<'a> TransmitContext<'a> {
/// Returns true if the signal was stored in a cell, false otherwise. /// Returns true if the signal was stored in a cell, false otherwise.
/// The target cell's state will be set to `Active` if it received the signal. /// The target cell's state will be set to `Active` if it received the signal.
/// The signal's `position` will be set to `pos`. /// The signal's `position` will be set to `pos`.
pub fn send<'b>(&'b mut self, pos: (usize, usize), mut signal: Signal) -> Option<Weak<Signal>> where 'a: 'b { pub fn send<'b>(&'b mut self, pos: (usize, usize), mut signal: Signal) -> Option<()> where 'a: 'b {
// SAFETY: we do not return any reference to any data borrowed in this function // SAFETY: we do not return any reference to any data borrowed in this function
// SAFETY: we only access `pane[pos].signal`, `pane[pos].state` and `pane.signals` // SAFETY: we only access `pane[pos].signal`, `pane[pos].state` and `pane.signals`
let pane = unsafe { self.pane_mut() }; let pane = unsafe { self.pane_mut() };
signal.set_position(pos); signal.set_position(pos);
match pane.set_signal(pos, signal) { pane.set_signal(pos, signal)?;
Some(signal) => { // SAFETY: we only access `pane[pos].state`
// SAFETY: we only access `pane[pos].state` pane.get_mut(pos).unwrap_or_else(|| unreachable!()).set_state(State::Active);
pane.get_mut(pos).unwrap_or_else(|| unreachable!()).set_state(State::Active);
Some(signal) Some(())
}
None => None
}
} }
/// Returns `Some((position.x + Δx, position.y + Δy))` iff `(x + Δx, y + Δy)` is inside the pane /// Returns `Some((position.x + Δx, position.y + Δy))` iff `(x + Δx, y + Δy)` is inside the pane

@ -1,5 +1,4 @@
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::rc::Weak;
mod signal; mod signal;
pub use signal::*; pub use signal::*;

@ -6,7 +6,7 @@ pub struct Pane {
width: NonZeroUsize, width: NonZeroUsize,
height: NonZeroUsize, height: NonZeroUsize,
signals: Vec<Weak<Signal>>, signals: Vec<(usize, usize)>,
} }
impl Pane { impl Pane {
@ -71,10 +71,11 @@ impl Pane {
/// - the tile accepts a signal (ie. it isn't empty) /// - the tile accepts a signal (ie. it isn't empty)
// SAFETY: may only access `self[pos].signal` and `self.signals` // SAFETY: may only access `self[pos].signal` and `self.signals`
#[inline] #[inline]
pub fn set_signal(&mut self, position: (usize, usize), signal: Signal) -> Option<Weak<Signal>> { pub fn set_signal(&mut self, position: (usize, usize), mut signal: Signal) -> Option<()> {
let signal = self.get_mut(position)?.set_signal(signal)?; signal.set_position(position);
self.signals.push(signal.clone()); self.get_mut(position)?.set_signal(signal)?;
Some(signal) self.signals.push(position);
Some(())
} }
#[inline] #[inline]
@ -116,11 +117,8 @@ impl Pane {
/// Calls [`Pane::transmit`] on all tiles with a signal /// Calls [`Pane::transmit`] on all tiles with a signal
fn transmit_all(&mut self) { fn transmit_all(&mut self) {
// TODO: store a second buffer and perform swap reads // TODO: store a second buffer and perform swap reads
for signal in std::mem::replace(&mut self.signals, vec![]) { for position in std::mem::replace(&mut self.signals, vec![]) {
if let Some(upgraded) = signal.upgrade() { let _ = self.transmit(position); // May return None if the signal was aliased
let position = upgraded.position();
let _ = self.transmit(position); // May return None if the signal was aliased
}
} }
} }

@ -1,6 +1,5 @@
use super::*; use super::*;
use dyn_clone::{clone_box, DynClone}; use dyn_clone::{clone_box, DynClone};
use std::rc::Rc;
mod wire; mod wire;
pub use wire::*; pub use wire::*;
@ -17,7 +16,7 @@ Cloning a `FullTile` results in a `FullTile` that does not have any signal.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct FullTile { pub struct FullTile {
cell: Option<AnyTile>, cell: Option<AnyTile>,
signal: Option<Rc<Signal>>, signal: Option<Signal>,
state: State, state: State,
} }
@ -40,12 +39,10 @@ impl FullTile {
} }
/// Returns Some(signal) iff self.cell.is_some() /// Returns Some(signal) iff self.cell.is_some()
pub(crate) fn set_signal(&mut self, signal: Signal) -> Option<Weak<Signal>> { pub(crate) fn set_signal(&mut self, signal: Signal) -> Option<()> {
if self.cell.is_some() { if self.cell.is_some() {
let rc = Rc::new(signal); self.signal = Some(signal);
let weak = Rc::downgrade(&rc); Some(())
self.signal = Some(rc);
Some(weak)
} else { } else {
None None
} }
@ -65,12 +62,12 @@ impl FullTile {
/// Returns the signal of this tile /// Returns the signal of this tile
#[inline] #[inline]
pub fn signal<'b>(&'b self) -> Option<&'b Rc<Signal>> { pub fn signal<'b>(&'b self) -> Option<&'b Signal> {
self.signal.as_ref() self.signal.as_ref()
} }
#[inline] #[inline]
pub fn take_signal(&mut self) -> Option<Rc<Signal>> { pub fn take_signal(&mut self) -> Option<Signal> {
std::mem::take(&mut self.signal) std::mem::take(&mut self.signal)
} }
@ -91,7 +88,7 @@ impl FullTile {
self.state = self.state.next(); self.state = self.state.next();
} }
pub fn into_raw_mut<'b>(&'b mut self) -> (&'b mut Option<AnyTile>, &'b mut Option<Rc<Signal>>, &'b mut State) { pub fn into_raw_mut<'b>(&'b mut self) -> (&'b mut Option<AnyTile>, &'b mut Option<Signal>, &'b mut State) {
(&mut self.cell, &mut self.signal, &mut self.state) (&mut self.cell, &mut self.signal, &mut self.state)
} }
} }
@ -126,7 +123,7 @@ pub trait Tile: DynClone + std::fmt::Debug {
} }
/// Function that will be called if the tile has a signal. /// Function that will be called if the tile has a signal.
fn transmit<'b>(&'b self, signal: Rc<Signal>, context: TransmitContext<'b>); fn transmit<'b>(&'b self, signal: Signal, context: TransmitContext<'b>);
/// Should return true iff the tile accepts a signal travelling in `Direction` /// Should return true iff the tile accepts a signal travelling in `Direction`
#[inline] #[inline]
@ -151,7 +148,7 @@ impl AnyTile {
} }
#[inline] #[inline]
pub fn transmit<'b>(&'b self, signal: Rc<Signal>, context: TransmitContext<'b>) { pub fn transmit<'b>(&'b self, signal: Signal, context: TransmitContext<'b>) {
self.0.transmit(signal, context) self.0.transmit(signal, context)
} }

@ -12,7 +12,7 @@ impl Wire {
} }
impl Tile for Wire { impl Tile for Wire {
fn transmit<'b>(&'b self, signal: Rc<Signal>, mut context: TransmitContext<'b>) { fn transmit<'b>(&'b self, signal: Signal, mut context: TransmitContext<'b>) {
for &direction in self.0.into_directions() { for &direction in self.0.into_directions() {
if direction == signal.direction().opposite() { if direction == signal.direction().opposite() {
continue; continue;
@ -41,7 +41,7 @@ impl Diode {
} }
impl Tile for Diode { impl Tile for Diode {
fn transmit<'b>(&'b self, signal: Rc<Signal>, mut context: TransmitContext<'b>) { fn transmit<'b>(&'b self, signal: Signal, mut context: TransmitContext<'b>) {
// Block signals coming from where the diode is looking // Block signals coming from where the diode is looking
if signal.direction().opposite() == self.0 { if signal.direction().opposite() == self.0 {
return; return;

Loading…
Cancel
Save