flare_core_runtime/signal/
composite.rs1use super::ShutdownSignal;
4use futures::future::select_all;
5use std::pin::Pin;
6
7pub struct CompositeSignal {
25 signals: Vec<Box<dyn ShutdownSignal>>,
26 name: String,
27}
28
29impl CompositeSignal {
30 pub fn new() -> Self {
32 Self {
33 signals: Vec::new(),
34 name: "composite".to_string(),
35 }
36 }
37
38 pub fn from_signals(signals: Vec<Box<dyn ShutdownSignal>>) -> Self {
40 Self {
41 signals,
42 name: "composite".to_string(),
43 }
44 }
45
46 #[allow(clippy::should_implement_trait)]
48 pub fn add(mut self, signal: Box<dyn ShutdownSignal>) -> Self {
49 self.signals.push(signal);
50 self
51 }
52
53 pub fn with_name(mut self, name: impl Into<String>) -> Self {
55 self.name = name.into();
56 self
57 }
58}
59
60impl Default for CompositeSignal {
61 fn default() -> Self {
62 Self::new()
63 }
64}
65
66impl ShutdownSignal for CompositeSignal {
67 fn wait(&mut self) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + '_>> {
68 if self.signals.is_empty() {
69 return Box::pin(std::future::pending::<()>());
71 }
72
73 let futures: Vec<_> = self.signals.iter_mut().map(|s| s.wait()).collect();
75
76 if futures.is_empty() {
77 return Box::pin(std::future::pending::<()>());
78 }
79
80 Box::pin(async move {
82 let (result, _index, _others) = select_all(futures).await;
83 result
84 })
85 }
86
87 fn name(&self) -> &str {
88 &self.name
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::signal::CtrlCSignal;
96
97 #[test]
98 fn test_composite_signal_new() {
99 let signal = CompositeSignal::new();
100 assert_eq!(signal.name(), "composite");
101 }
102
103 #[test]
104 fn test_composite_signal_add() {
105 let signal = CompositeSignal::new()
106 .add(Box::new(CtrlCSignal::new()))
107 .add(Box::new(CtrlCSignal::new()));
108
109 assert_eq!(signal.name(), "composite");
110 }
111
112 #[test]
113 fn test_composite_signal_from_signals() {
114 let signal = CompositeSignal::from_signals(vec![
115 Box::new(CtrlCSignal::new()),
116 Box::new(CtrlCSignal::new()),
117 ]);
118
119 assert_eq!(signal.name(), "composite");
120 }
121}