platform_core/
shutdown.rs1use std::fmt::Debug;
2use std::sync::Arc;
3use tokio::sync::watch;
4
5#[derive(Clone)]
6pub struct Shutdown {
7 sender: Arc<watch::Sender<bool>>,
8 receiver: watch::Receiver<bool>,
9}
10
11impl Debug for Shutdown {
12 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13 formatter.debug_struct("Shutdown").finish_non_exhaustive()
14 }
15}
16
17impl Shutdown {
18 pub fn new() -> Self {
19 let (sender, receiver) = watch::channel(false);
20 Self {
21 sender: Arc::new(sender),
22 receiver,
23 }
24 }
25
26 pub fn signal(&self) {
27 let _ = self.sender.send(true);
28 }
29
30 pub fn subscribe(&self) -> watch::Receiver<bool> {
31 self.receiver.clone()
32 }
33
34 pub async fn wait_for_signal() {
35 let ctrl_c = async {
36 tokio::signal::ctrl_c()
37 .await
38 .expect("failed to install Ctrl+C handler");
39 };
40
41 #[cfg(unix)]
42 let terminate = async {
43 tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
44 .expect("failed to install signal handler")
45 .recv()
46 .await;
47 };
48
49 #[cfg(not(unix))]
50 let terminate = std::future::pending::<()>();
51
52 tokio::select! {
53 () = ctrl_c => {},
54 () = terminate => {},
55 }
56 }
57}
58
59impl Default for Shutdown {
60 fn default() -> Self {
61 Self::new()
62 }
63}