💹 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::rc::Rc;
use super::*;
/** 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
}
#
# 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.
#[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() };
// SAFETY: `pane[position].signal` is not borrowed mutably
@ -170,7 +169,7 @@ pub struct 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;
// SAFETY: no mutable accesses to `∀x, pane[x].cell` are made by `TransmitContext`
let tile: &AnyTile = unsafe {
@ -240,22 +239,18 @@ impl<'a> TransmitContext<'a> {
/// 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 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 only access `pane[pos].signal`, `pane[pos].state` and `pane.signals`
let pane = unsafe { self.pane_mut() };
signal.set_position(pos);
match pane.set_signal(pos, signal) {
Some(signal) => {
pane.set_signal(pos, signal)?;
// SAFETY: we only access `pane[pos].state`
pane.get_mut(pos).unwrap_or_else(|| unreachable!()).set_state(State::Active);
Some(signal)
}
None => None
}
Some(())
}
/// 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::rc::Weak;
mod signal;
pub use signal::*;

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

@ -1,6 +1,5 @@
use super::*;
use dyn_clone::{clone_box, DynClone};
use std::rc::Rc;
mod wire;
pub use wire::*;
@ -17,7 +16,7 @@ Cloning a `FullTile` results in a `FullTile` that does not have any signal.
#[derive(Clone, Debug)]
pub struct FullTile {
cell: Option<AnyTile>,
signal: Option<Rc<Signal>>,
signal: Option<Signal>,
state: State,
}
@ -40,12 +39,10 @@ impl FullTile {
}
/// 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() {
let rc = Rc::new(signal);
let weak = Rc::downgrade(&rc);
self.signal = Some(rc);
Some(weak)
self.signal = Some(signal);
Some(())
} else {
None
}
@ -65,12 +62,12 @@ impl FullTile {
/// Returns the signal of this tile
#[inline]
pub fn signal<'b>(&'b self) -> Option<&'b Rc<Signal>> {
pub fn signal<'b>(&'b self) -> Option<&'b Signal> {
self.signal.as_ref()
}
#[inline]
pub fn take_signal(&mut self) -> Option<Rc<Signal>> {
pub fn take_signal(&mut self) -> Option<Signal> {
std::mem::take(&mut self.signal)
}
@ -91,7 +88,7 @@ impl FullTile {
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)
}
}
@ -126,7 +123,7 @@ pub trait Tile: DynClone + std::fmt::Debug {
}
/// 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`
#[inline]
@ -151,7 +148,7 @@ impl AnyTile {
}
#[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)
}

@ -12,7 +12,7 @@ impl 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() {
if direction == signal.direction().opposite() {
continue;
@ -41,7 +41,7 @@ impl 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
if signal.direction().opposite() == self.0 {
return;

Loading…
Cancel
Save