fix: remove Owner from thread-local when it is ordinarily dropped, to ensure cleanup (closes #2942) (#2944)

This commit is contained in:
Greg Johnston 2024-09-07 07:01:54 -04:00 committed by GitHub
parent 4a76aead68
commit 57bd343f4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 1 deletions

View file

@ -59,7 +59,7 @@ pub trait ExtendResponse: Sized {
// drop the owner, cleaning up the reactive runtime, // drop the owner, cleaning up the reactive runtime,
// once the stream is over // once the stream is over
.chain(once(async move { .chain(once(async move {
drop(owner); owner.unset();
Default::default() Default::default()
})), })),
)); ));

View file

@ -55,6 +55,12 @@ pub struct Owner {
pub(crate) shared_context: Option<Arc<dyn SharedContext + Send + Sync>>, pub(crate) shared_context: Option<Arc<dyn SharedContext + Send + Sync>>,
} }
impl PartialEq for Owner {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
thread_local! { thread_local! {
static OWNER: RefCell<Option<Owner>> = Default::default(); static OWNER: RefCell<Option<Owner>> = Default::default();
} }
@ -241,6 +247,15 @@ impl Owner {
self.shared_context.clone() self.shared_context.clone()
} }
/// Removes this from its state as the thread-local owner and drops it.
pub fn unset(self) {
OWNER.with_borrow_mut(|owner| {
if owner.as_ref() == Some(&self) {
mem::take(owner);
}
})
}
/// Returns the current [`SharedContext`], if any. /// Returns the current [`SharedContext`], if any.
#[cfg(feature = "hydration")] #[cfg(feature = "hydration")]
pub fn current_shared_context( pub fn current_shared_context(

View file

@ -313,6 +313,7 @@ impl<T, S: Storage<T>> StoredValue<T, S> {
/// assert_eq!(last, None); /// assert_eq!(last, None);
/// assert_eq!(length_fn(), None); /// assert_eq!(length_fn(), None);
/// ``` /// ```
#[track_caller]
pub fn try_with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> Option<U> { pub fn try_with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> Option<U> {
S::try_with(self.node, fun) S::try_with(self.node, fun)
} }
@ -347,6 +348,7 @@ impl<T, S: Storage<T>> StoredValue<T, S> {
/// assert_eq!(sum, 6); /// assert_eq!(sum, 6);
/// assert_eq!(length_fn(), 3); /// assert_eq!(length_fn(), 3);
/// ``` /// ```
#[track_caller]
pub fn with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> U { pub fn with_value<U>(&self, fun: impl FnOnce(&T) -> U) -> U {
self.try_with_value(fun) self.try_with_value(fun)
.unwrap_or_else(unwrap_signal!(self)) .unwrap_or_else(unwrap_signal!(self))