Merge pull request #2496 from iced-rs/abortable-tasks

Abortable `Task`
This commit is contained in:
Héctor Ramón 2024-07-10 15:42:38 +02:00 committed by GitHub
commit 70f44a6e26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 19 deletions

View file

@ -55,24 +55,6 @@ impl<T> Task<T> {
Self::stream(stream.map(f)) Self::stream(stream.map(f))
} }
/// Creates a new [`Task`] that runs the given [`Future`] and produces
/// its output.
pub fn future(future: impl Future<Output = T> + MaybeSend + 'static) -> Self
where
T: 'static,
{
Self::stream(stream::once(future))
}
/// Creates a new [`Task`] that runs the given [`Stream`] and produces
/// each of its items.
pub fn stream(stream: impl Stream<Item = T> + MaybeSend + 'static) -> Self
where
T: 'static,
{
Self(Some(boxed_stream(stream.map(Action::Output))))
}
/// Combines the given tasks and produces a single [`Task`] that will run all of them /// Combines the given tasks and produces a single [`Task`] that will run all of them
/// in parallel. /// in parallel.
pub fn batch(tasks: impl IntoIterator<Item = Self>) -> Self pub fn batch(tasks: impl IntoIterator<Item = Self>) -> Self
@ -176,6 +158,61 @@ impl<T> Task<T> {
))), ))),
} }
} }
/// Creates a new [`Task`] that can be aborted with the returned [`Handle`].
pub fn abortable(self) -> (Self, Handle)
where
T: 'static,
{
match self.0 {
Some(stream) => {
let (stream, handle) = stream::abortable(stream);
(Self(Some(boxed_stream(stream))), Handle(Some(handle)))
}
None => (Self(None), Handle(None)),
}
}
/// Creates a new [`Task`] that runs the given [`Future`] and produces
/// its output.
pub fn future(future: impl Future<Output = T> + MaybeSend + 'static) -> Self
where
T: 'static,
{
Self::stream(stream::once(future))
}
/// Creates a new [`Task`] that runs the given [`Stream`] and produces
/// each of its items.
pub fn stream(stream: impl Stream<Item = T> + MaybeSend + 'static) -> Self
where
T: 'static,
{
Self(Some(boxed_stream(stream.map(Action::Output))))
}
}
/// A handle to a [`Task`] that can be used for aborting it.
#[derive(Debug, Clone)]
pub struct Handle(Option<stream::AbortHandle>);
impl Handle {
/// Aborts the [`Task`] of this [`Handle`].
pub fn abort(&self) {
if let Some(handle) = &self.0 {
handle.abort();
}
}
/// Returns `true` if the [`Task`] of this [`Handle`] has been aborted.
pub fn is_aborted(&self) -> bool {
if let Some(handle) = &self.0 {
handle.is_aborted()
} else {
true
}
}
} }
impl<T> Task<Option<T>> { impl<T> Task<Option<T>> {

View file

@ -202,9 +202,14 @@ pub use crate::core::{
Length, Padding, Pixels, Point, Radians, Rectangle, Rotation, Shadow, Size, Length, Padding, Pixels, Point, Radians, Rectangle, Rotation, Shadow, Size,
Theme, Transformation, Vector, Theme, Transformation, Vector,
}; };
pub use crate::runtime::{exit, Task}; pub use crate::runtime::exit;
pub use iced_futures::Subscription; pub use iced_futures::Subscription;
pub mod task {
//! Create runtime tasks.
pub use crate::runtime::task::{Handle, Task};
}
pub mod clipboard { pub mod clipboard {
//! Access the clipboard. //! Access the clipboard.
pub use crate::runtime::clipboard::{ pub use crate::runtime::clipboard::{
@ -309,6 +314,7 @@ pub use executor::Executor;
pub use font::Font; pub use font::Font;
pub use renderer::Renderer; pub use renderer::Renderer;
pub use settings::Settings; pub use settings::Settings;
pub use task::Task;
#[doc(inline)] #[doc(inline)]
pub use application::application; pub use application::application;