stoppable_task.rs 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. use async_std::sync::Arc;
  2. use futures::{Future, FutureExt};
  3. use smol::Executor;
  4. pub type StoppableTaskPtr = Arc<StoppableTask>;
  5. pub struct StoppableTask {
  6. stop_send: smol::channel::Sender<()>,
  7. stop_recv: smol::channel::Receiver<()>,
  8. }
  9. impl StoppableTask {
  10. pub fn new() -> Arc<Self> {
  11. let (stop_send, stop_recv) = smol::channel::unbounded();
  12. Arc::new(Self { stop_send, stop_recv })
  13. }
  14. pub async fn stop(&self) {
  15. // Ignore any errors from this send
  16. let _ = self.stop_send.send(()).await;
  17. }
  18. pub fn start<'a, MainFut, StopFut, StopFn, Error>(
  19. self: Arc<Self>,
  20. main: MainFut,
  21. stop_handler: StopFn,
  22. stop_value: Error,
  23. executor: Arc<Executor<'a>>,
  24. ) where
  25. MainFut: Future<Output = std::result::Result<(), Error>> + Send + 'a,
  26. StopFut: Future<Output = ()> + Send,
  27. StopFn: FnOnce(std::result::Result<(), Error>) -> StopFut + Send + 'a,
  28. Error: std::error::Error + Send + 'a,
  29. {
  30. executor
  31. .spawn(async move {
  32. let result = futures::select! {
  33. _ = self.stop_recv.recv().fuse() => Err(stop_value),
  34. result = main.fuse() => result
  35. };
  36. stop_handler(result).await;
  37. })
  38. .detach();
  39. }
  40. }