Trigger::{add, remove}_subscriber are now private.

Subscribers must be gathered by `Trigger::gather_subscribers`.

This inverts the responsibility of gathering the effects from the caller to the trigger.
This will allow us to add more effect stacks in the future (such as an async task-local effect stack) without changing as much code.
This commit is contained in:
Filipe Rodrigues 2024-12-20 20:11:43 +00:00
parent 6150fac6fb
commit 06dabd431e
Signed by: zenithsiz
SSH Key Fingerprint: SHA256:Mb5ppb3Sh7IarBO/sBTXLHbYEOz37hJAlslLQPPAPaU
5 changed files with 25 additions and 20 deletions

View File

@ -5,7 +5,7 @@
// Imports
use {
crate::{effect, signal, SignalBorrow, SignalBorrowMut, SignalUpdate, SignalWith, Trigger},
crate::{signal, SignalBorrow, SignalBorrowMut, SignalUpdate, SignalWith, Trigger},
core::{
cell::{self, RefCell},
fmt,
@ -99,10 +99,7 @@ impl<F: Future> AsyncSignal<F> {
#[must_use]
#[track_caller]
pub fn borrow_inner(&self) -> Option<BorrowRef<'_, F::Output>> {
// If there's an effect running, add it to the subscribers
if let Some(effect) = effect::running() {
self.inner.waker.trigger.add_subscriber(effect);
}
self.inner.waker.trigger.gather_subscribers();
let borrow = self.inner.value.borrow();
borrow.is_some().then(|| BorrowRef(borrow))

View File

@ -32,7 +32,7 @@
// Imports
use {
crate::{effect, Effect, SignalBorrow, SignalWith, Trigger},
crate::{Effect, SignalBorrow, SignalWith, Trigger},
core::{
cell::{self, RefCell},
fmt,
@ -88,9 +88,7 @@ impl<T: 'static, F: ?Sized> SignalBorrow for Derived<T, F> {
#[track_caller]
fn borrow(&self) -> Self::Ref<'_> {
if let Some(effect) = effect::running() {
self.effect.inner_fn().trigger.add_subscriber(effect);
}
self.effect.inner_fn().trigger.gather_subscribers();
let effect_fn = self.effect.inner_fn();
let value = effect_fn.value.borrow();

View File

@ -2,7 +2,7 @@
// Imports
use {
crate::{effect, Effect, SignalBorrow, SignalWith, Trigger},
crate::{Effect, SignalBorrow, SignalWith, Trigger},
core::{
cell::{self, RefCell},
fmt,
@ -58,9 +58,7 @@ impl<T: 'static, F: ?Sized> SignalBorrow for Memo<T, F> {
#[track_caller]
fn borrow(&self) -> Self::Ref<'_> {
if let Some(effect) = effect::running() {
self.effect.inner_fn().trigger.add_subscriber(effect);
}
self.effect.inner_fn().trigger.gather_subscribers();
let effect_fn = self.effect.inner_fn();
let value = effect_fn.value.borrow();

View File

@ -23,7 +23,7 @@ pub use ops::{
// Imports
use {
crate::{effect, Trigger},
crate::Trigger,
core::{
cell::{self, RefCell},
fmt,
@ -94,9 +94,7 @@ impl<T: ?Sized + 'static> SignalBorrow for Signal<T> {
#[track_caller]
fn borrow(&self) -> Self::Ref<'_> {
if let Some(effect) = effect::running() {
self.inner.trigger.add_subscriber(effect);
}
self.inner.trigger.gather_subscribers();
let borrow = self
.inner

View File

@ -5,7 +5,7 @@
// Imports
use {
crate::{Effect, WeakEffect},
crate::{effect, Effect, WeakEffect},
core::{cell::RefCell, fmt, marker::Unsize},
std::{
collections::{hash_map, HashMap},
@ -112,11 +112,25 @@ impl Trigger {
}
}
/// Gathers all effects depending on this trigger.
///
/// When triggering this trigger, all effects active during this gathering
/// will be re-run.
///
/// You can gather multiple times without removing the previous gathered
/// effects. Previous effects will only be removed when they are dropped.
// TODO: Should we remove all existing subscribers before gathering them?
pub fn gather_subscribers(&self) {
if let Some(effect) = effect::running() {
self.add_subscriber(effect);
}
}
/// Adds a subscriber to this trigger.
///
/// Returns if the subscriber already existed.
#[track_caller]
pub fn add_subscriber<S: IntoSubscriber>(&self, subscriber: S) -> bool {
fn add_subscriber<S: IntoSubscriber>(&self, subscriber: S) -> bool {
let mut subscribers = self.inner.subscribers.borrow_mut();
match subscribers.entry(subscriber.into_subscriber()) {
hash_map::Entry::Occupied(mut entry) => {
@ -134,7 +148,7 @@ impl Trigger {
///
/// Returns if the subscriber existed
#[track_caller]
pub fn remove_subscriber<S: IntoSubscriber>(&self, subscriber: S) -> bool {
fn remove_subscriber<S: IntoSubscriber>(&self, subscriber: S) -> bool {
let mut subscribers = self.inner.subscribers.borrow_mut();
subscribers.remove(&subscriber.into_subscriber()).is_some()
}