Honor clones of task::Handle with abort_on_drop
This commit is contained in:
parent
2a2e20b0a3
commit
6d50c62bc7
1 changed files with 42 additions and 21 deletions
|
|
@ -9,6 +9,7 @@ use crate::futures::{boxed_stream, BoxStream, MaybeSend};
|
||||||
use crate::Action;
|
use crate::Action;
|
||||||
|
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// A set of concurrent actions to be performed by the iced runtime.
|
/// A set of concurrent actions to be performed by the iced runtime.
|
||||||
///
|
///
|
||||||
|
|
@ -183,16 +184,16 @@ impl<T> Task<T> {
|
||||||
(
|
(
|
||||||
Self(Some(boxed_stream(stream))),
|
Self(Some(boxed_stream(stream))),
|
||||||
Handle {
|
Handle {
|
||||||
raw: Some(handle),
|
internal: InternalHandle::Manual(handle),
|
||||||
abort_on_drop: false,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => (
|
None => (
|
||||||
Self(None),
|
Self(None),
|
||||||
Handle {
|
Handle {
|
||||||
raw: None,
|
internal: InternalHandle::Manual(
|
||||||
abort_on_drop: false,
|
stream::AbortHandle::new_pair().0,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -220,44 +221,64 @@ impl<T> Task<T> {
|
||||||
/// A handle to a [`Task`] that can be used for aborting it.
|
/// A handle to a [`Task`] that can be used for aborting it.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Handle {
|
pub struct Handle {
|
||||||
raw: Option<stream::AbortHandle>,
|
internal: InternalHandle,
|
||||||
abort_on_drop: bool,
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum InternalHandle {
|
||||||
|
Manual(stream::AbortHandle),
|
||||||
|
AbortOnDrop(Arc<stream::AbortHandle>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalHandle {
|
||||||
|
pub fn as_ref(&self) -> &stream::AbortHandle {
|
||||||
|
match self {
|
||||||
|
InternalHandle::Manual(handle) => handle,
|
||||||
|
InternalHandle::AbortOnDrop(handle) => handle.as_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Handle {
|
impl Handle {
|
||||||
/// Aborts the [`Task`] of this [`Handle`].
|
/// Aborts the [`Task`] of this [`Handle`].
|
||||||
pub fn abort(&self) {
|
pub fn abort(&self) {
|
||||||
if let Some(handle) = &self.raw {
|
self.internal.as_ref().abort();
|
||||||
handle.abort();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new [`Handle`] that will call [`Handle::abort`] whenever
|
/// Returns a new [`Handle`] that will call [`Handle::abort`] whenever
|
||||||
/// it is dropped.
|
/// all of its instances are dropped.
|
||||||
|
///
|
||||||
|
/// If a [`Handle`] is cloned, [`Handle::abort`] will only be called
|
||||||
|
/// once all of the clones are dropped.
|
||||||
///
|
///
|
||||||
/// This can be really useful if you do not want to worry about calling
|
/// This can be really useful if you do not want to worry about calling
|
||||||
/// [`Handle::abort`] yourself.
|
/// [`Handle::abort`] yourself.
|
||||||
pub fn abort_on_drop(mut self) -> Self {
|
pub fn abort_on_drop(self) -> Self {
|
||||||
Self {
|
match &self.internal {
|
||||||
raw: self.raw.take(),
|
InternalHandle::Manual(handle) => Self {
|
||||||
abort_on_drop: true,
|
internal: InternalHandle::AbortOnDrop(Arc::new(handle.clone())),
|
||||||
|
},
|
||||||
|
InternalHandle::AbortOnDrop(_) => self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the [`Task`] of this [`Handle`] has been aborted.
|
/// Returns `true` if the [`Task`] of this [`Handle`] has been aborted.
|
||||||
pub fn is_aborted(&self) -> bool {
|
pub fn is_aborted(&self) -> bool {
|
||||||
if let Some(handle) = &self.raw {
|
self.internal.as_ref().is_aborted()
|
||||||
handle.is_aborted()
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Handle {
|
impl Drop for Handle {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.abort_on_drop {
|
if let InternalHandle::AbortOnDrop(handle) = &mut self.internal {
|
||||||
self.abort();
|
let handle = std::mem::replace(
|
||||||
|
handle,
|
||||||
|
Arc::new(stream::AbortHandle::new_pair().0),
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(handle) = Arc::into_inner(handle) {
|
||||||
|
handle.abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue