1use crate::{notify_once::NotifyOnce, server::Address};
2use std::{
3 sync::{
4 atomic::{AtomicUsize, Ordering},
5 Arc, Mutex,
6 },
7 time::Duration,
8};
9use tokio::time::sleep;
10
11#[derive(Clone, Debug, Default)]
30pub struct Control {
31 inner: Arc<ControlInner>,
32}
33
34#[derive(Debug, Default)]
35struct ControlInner {
36 conn_count: AtomicUsize,
37 shutdown: NotifyOnce,
38 graceful: NotifyOnce,
39 graceful_dur: Mutex<Option<Duration>>,
40 conn_end: NotifyOnce,
41}
42
43impl Control {
44 pub fn new() -> Self {
46 Self::default()
47 }
48
49 pub fn connection_count(&self) -> usize {
52 self.inner.conn_count.load(Ordering::SeqCst)
53 }
54
55 pub fn shutdown(&self) {
57 self.inner.shutdown.notify_waiters();
58 }
59
60 pub fn graceful_shutdown(&self, duration: Option<Duration>) {
64 *self.inner.graceful_dur.lock().unwrap() = duration;
65
66 self.inner.graceful.notify_waiters();
67 }
68
69 pub(crate) async fn wait_shutdown(&self) {
70 self.inner.shutdown.notified().await;
71 }
72
73 pub(crate) async fn wait_graceful_shutdown(&self) {
74 self.inner.graceful.notified().await;
75 }
76
77 pub(crate) async fn wait_connections_end(&self) {
78 if self.inner.conn_count.load(Ordering::SeqCst) == 0 {
79 return;
80 }
81
82 let deadline = *self.inner.graceful_dur.lock().unwrap();
83
84 match deadline {
85 Some(duration) => tokio::select! {
86 biased;
87 _ = sleep(duration) => self.shutdown(),
88 _ = self.inner.conn_end.notified() => (),
89 },
90 None => self.inner.conn_end.notified().await,
91 }
92 }
93
94 pub(crate) fn watcher(&self) -> Watcher {
95 Watcher::new(self.clone())
96 }
97}
98
99#[derive(Clone, Debug)]
105pub struct Handle<A: Address> {
106 addr: Arc<AddrSlot<A>>,
107 control: Control,
108}
109
110#[derive(Debug)]
111struct AddrSlot<A: Address> {
112 addr: Mutex<Option<A>>,
113 addr_notify: NotifyOnce,
114}
115
116impl<A: Address> Default for AddrSlot<A> {
118 fn default() -> Self {
119 Self {
120 addr: Default::default(),
121 addr_notify: Default::default(),
122 }
123 }
124}
125
126impl<A: Address> Default for Handle<A> {
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132impl<A: Address> Handle<A> {
133 pub fn new() -> Self {
135 Self::with_control(Control::new())
136 }
137
138 pub fn with_control(control: Control) -> Self {
144 Self {
145 addr: Arc::new(AddrSlot::default()),
146 control,
147 }
148 }
149
150 pub fn control(&self) -> Control {
152 self.control.clone()
153 }
154
155 pub fn connection_count(&self) -> usize {
157 self.control.connection_count()
158 }
159
160 pub fn shutdown(&self) {
162 self.control.shutdown();
163 }
164
165 pub fn graceful_shutdown(&self, duration: Option<Duration>) {
169 self.control.graceful_shutdown(duration);
170 }
171
172 pub async fn listening(&self) -> Option<A> {
176 self.addr.addr_notify.notified().await;
181
182 self.addr.addr.lock().unwrap().clone()
183 }
184
185 pub(crate) fn notify_listening(&self, addr: Option<A>) {
186 *self.addr.addr.lock().unwrap() = addr;
187
188 self.addr.addr_notify.notify_waiters();
189 }
190
191 pub(crate) fn watcher(&self) -> Watcher {
192 self.control.watcher()
193 }
194
195 pub(crate) async fn wait_shutdown(&self) {
196 self.control.wait_shutdown().await;
197 }
198
199 pub(crate) async fn wait_graceful_shutdown(&self) {
200 self.control.wait_graceful_shutdown().await;
201 }
202
203 pub(crate) async fn wait_connections_end(&self) {
204 self.control.wait_connections_end().await;
205 }
206}
207
208pub(crate) struct Watcher {
209 control: Control,
210}
211
212impl Watcher {
213 fn new(control: Control) -> Self {
214 control.inner.conn_count.fetch_add(1, Ordering::SeqCst);
215
216 Self { control }
217 }
218
219 pub(crate) async fn wait_graceful_shutdown(&self) {
220 self.control.wait_graceful_shutdown().await
221 }
222
223 pub(crate) async fn wait_shutdown(&self) {
224 self.control.wait_shutdown().await
225 }
226}
227
228impl Drop for Watcher {
229 fn drop(&mut self) {
230 let count = self.control.inner.conn_count.fetch_sub(1, Ordering::SeqCst) - 1;
231
232 if count == 0 && self.control.inner.graceful.is_notified() {
233 self.control.inner.conn_end.notify_waiters();
234 }
235 }
236}
237
238#[cfg(test)]
239mod tests {
240 use super::{Control, Handle};
241 use std::{net::SocketAddr, time::Duration};
242
243 #[tokio::test]
244 async fn listening_returns_none_after_bind_failure() {
245 let handle = Handle::<SocketAddr>::new();
246
247 handle.notify_listening(None);
249
250 let addr = tokio::time::timeout(Duration::from_secs(1), handle.listening())
251 .await
252 .expect("listening() should resolve immediately after a bind failure");
253
254 assert_eq!(addr, None);
255 }
256
257 #[tokio::test]
258 async fn listening_returns_addr_after_successful_bind() {
259 let handle = Handle::<SocketAddr>::new();
260 let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
261
262 handle.notify_listening(Some(addr));
263
264 let resolved = tokio::time::timeout(Duration::from_secs(1), handle.listening())
265 .await
266 .expect("listening() should resolve immediately");
267
268 assert_eq!(resolved, Some(addr));
269 }
270
271 #[tokio::test]
272 async fn control_is_shared_between_handles() {
273 let control = Control::new();
274 let first = Handle::<SocketAddr>::with_control(control.clone());
275 let second = Handle::<SocketAddr>::with_control(control.clone());
276
277 assert!(std::sync::Arc::ptr_eq(
278 &first.control.inner,
279 &second.control.inner
280 ));
281 assert!(std::sync::Arc::ptr_eq(&control.inner, &first.control.inner));
282 }
283}