protocol_jobs_manager.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. use async_std::sync::Mutex;
  2. use futures::Future;
  3. use log::*;
  4. use smol::Task;
  5. use std::sync::Arc;
  6. use crate::{error::Result, net::ChannelPtr, system::ExecutorPtr};
  7. /// Pointer to protocol jobs manager.
  8. pub type ProtocolJobsManagerPtr = Arc<ProtocolJobsManager>;
  9. /// Manages the tasks for the network protocol. Used by other connection
  10. /// protocols to handle asynchronous task execution across the network. Runs all
  11. /// tasks that are handed to it on an executor that has stopping functionality.
  12. pub struct ProtocolJobsManager {
  13. name: &'static str,
  14. channel: ChannelPtr,
  15. tasks: Mutex<Vec<Task<Result<()>>>>,
  16. }
  17. impl ProtocolJobsManager {
  18. /// Create a new protocol jobs manager.
  19. pub fn new(name: &'static str, channel: ChannelPtr) -> Arc<Self> {
  20. Arc::new(Self { name, channel, tasks: Mutex::new(Vec::new()) })
  21. }
  22. /// Runs the task on an executor. Prepares to stop all tasks when the
  23. /// channel is closed.
  24. pub fn start(self: Arc<Self>, executor: ExecutorPtr<'_>) {
  25. executor.spawn(self.handle_stop()).detach()
  26. }
  27. /// Spawns a new task and adds it to the internal queue.
  28. pub async fn spawn<'a, F>(&self, future: F, executor: ExecutorPtr<'a>)
  29. where
  30. F: Future<Output = Result<()>> + Send + 'a,
  31. {
  32. self.tasks.lock().await.push(executor.spawn(future))
  33. }
  34. /// Waits for a stop signal, then closes all tasks. Insures that all tasks
  35. /// are stopped when a channel closes. Called in start().
  36. async fn handle_stop(self: Arc<Self>) {
  37. let stop_sub = self.channel.clone().subscribe_stop().await;
  38. // Wait for the stop signal
  39. // Not interested in the exact error
  40. let _ = stop_sub.receive().await;
  41. self.close_all_tasks().await
  42. }
  43. /// Closes all open tasks. Takes all the tasks from the internal queue and
  44. /// closes them.
  45. async fn close_all_tasks(self: Arc<Self>) {
  46. debug!(target: "net",
  47. "ProtocolJobsManager::close_all_tasks() [START, name={}, addr={}]",
  48. self.name,
  49. self.channel.address()
  50. );
  51. // Take all the tasks from our internal queue...
  52. let tasks = std::mem::take(&mut *self.tasks.lock().await);
  53. for task in tasks {
  54. // ... and cancel them
  55. let _ = task.cancel().await;
  56. }
  57. }
  58. }