stoppable_task.rs 1.4 KB

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