diff --git a/src/session/model/session.rs b/src/session/model/session.rs index db42ca48..7f0859b8 100644 --- a/src/session/model/session.rs +++ b/src/session/model/session.rs @@ -67,7 +67,7 @@ mod imp { #[properties(wrapper_type = super::Session)] pub struct Session { /// The Matrix client for this session. - client: TokioDrop, + client: OnceCell>, /// The list model of the sidebar. #[property(get = Self::sidebar_list_model)] sidebar_list_model: OnceCell, @@ -153,7 +153,7 @@ mod imp { /// Set the Matrix client for this session. pub(super) fn set_client(&self, client: Client) { self.client - .set(client) + .set(TokioDrop::new(client)) .expect("client should be uninitialized"); let obj = self.obj(); diff --git a/src/session/view/content/room_history/message_toolbar/mod.rs b/src/session/view/content/room_history/message_toolbar/mod.rs index 1ceda34d..9993dd9c 100644 --- a/src/session/view/content/room_history/message_toolbar/mod.rs +++ b/src/session/view/content/room_history/message_toolbar/mod.rs @@ -813,8 +813,7 @@ mod imp { } future::Either::Right((response, _)) => { // The linux location stream requires a tokio executor when dropped. - let stream_drop = TokioDrop::new(); - let _ = stream_drop.set(location_stream); + let _ = TokioDrop::new(location_stream); if response == gtk::ResponseType::Ok { break; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 48b0f486..c17bec4b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -3,8 +3,9 @@ use std::{ borrow::Cow, cell::{Cell, OnceCell, RefCell}, - fmt, fs, io, - io::Write, + fmt, fs, + io::{self, Write}, + ops::Deref, path::{Path, PathBuf}, rc::{Rc, Weak}, sync::{Arc, LazyLock}, @@ -384,36 +385,30 @@ impl AsyncAction { } } -/// A type that requires the tokio runtime to be running when dropped. -/// -/// This is basically usable as a [`OnceCell`]. +/// A wrapper that requires the tokio runtime to be running when dropped. #[derive(Debug, Clone)] -pub struct TokioDrop(OnceCell); +pub struct TokioDrop(Option); impl TokioDrop { - /// Create a new empty `TokioDrop`; - pub fn new() -> Self { - Self::default() + /// Create a new `TokioDrop` wrapping the given type. + pub fn new(value: T) -> Self { + Self(Some(value)) } +} - /// Gets a reference to the underlying value. - /// - /// Returns `None` if the cell is empty. - pub fn get(&self) -> Option<&T> { - self.0.get() - } +impl Deref for TokioDrop { + type Target = T; - /// Sets the contents of this cell to `value`. - /// - /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was full. - pub(crate) fn set(&self, value: T) -> Result<(), T> { - self.0.set(value) + fn deref(&self) -> &Self::Target { + self.0 + .as_ref() + .expect("TokioDrop should always contain a value") } } -impl Default for TokioDrop { - fn default() -> Self { - Self(Default::default()) +impl From for TokioDrop { + fn from(value: T) -> Self { + Self::new(value) } } @@ -421,35 +416,12 @@ impl Drop for TokioDrop { fn drop(&mut self) { let _guard = RUNTIME.enter(); - if let Some(inner) = self.0.take() { - drop(inner); + if let Some(value) = self.0.take() { + drop(value); } } } -impl glib::property::Property for TokioDrop { - type Value = T::Value; -} - -impl glib::property::PropertyGet for TokioDrop { - type Value = T; - - fn get R>(&self, f: F) -> R { - f(self.get().unwrap()) - } -} - -impl glib::property::PropertySet for TokioDrop { - type SetValue = T; - - fn set(&self, v: Self::SetValue) { - assert!( - self.set(v).is_ok(), - "TokioDrop value was already initialized" - ); - } -} - /// The state of a resource that can be loaded. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, glib::Enum)] #[enum_type(name = "LoadingState")]