1#![allow(clippy::missing_panics_doc)]
2use std::sync::{Arc, atomic::AtomicBool, atomic::Ordering};
3use std::task::{Context, Poll, ready};
4use std::{future::Future, io, pin::Pin};
5
6use async_channel::Sender;
7use ntex_rt::signals::Signal;
8
9use crate::manager::ServerCommand;
10
11#[derive(Debug)]
12pub(crate) struct ServerShared {
13 pub(crate) paused: AtomicBool,
14}
15
16#[derive(Debug)]
18pub struct Server<T> {
19 shared: Arc<ServerShared>,
20 cmd: Sender<ServerCommand<T>>,
21 stop: Option<oneshot::AsyncReceiver<()>>,
22}
23
24impl<T> Server<T> {
25 pub(crate) fn new(cmd: Sender<ServerCommand<T>>, shared: Arc<ServerShared>) -> Self {
26 Server {
27 cmd,
28 shared,
29 stop: None,
30 }
31 }
32
33 pub fn builder() -> crate::net::ServerBuilder {
35 crate::net::ServerBuilder::default()
36 }
37
38 pub(crate) fn signal(&self, sig: Signal) {
39 let _ = self.cmd.try_send(ServerCommand::Signal(sig));
40 }
41
42 pub fn process(&self, item: T) -> Result<(), T> {
44 if self.shared.paused.load(Ordering::Acquire) {
45 Err(item)
46 } else if let Err(e) = self.cmd.try_send(ServerCommand::Item(item)) {
47 if let ServerCommand::Item(item) = e.into_inner() {
48 Err(item)
49 } else {
50 panic!()
51 }
52 } else {
53 Ok(())
54 }
55 }
56
57 pub fn pause(&self) -> impl Future<Output = ()> + use<T> {
62 let (tx, rx) = oneshot::channel();
63 let _ = self.cmd.try_send(ServerCommand::Pause(tx));
64 async move {
65 let _ = rx.await;
66 }
67 }
68
69 pub fn resume(&self) -> impl Future<Output = ()> + use<T> {
71 let (tx, rx) = oneshot::channel();
72 let _ = self.cmd.try_send(ServerCommand::Resume(tx));
73 async move {
74 let _ = rx.await;
75 }
76 }
77
78 pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> + use<T> {
82 let (tx, rx) = oneshot::channel();
83 let _ = self.cmd.try_send(ServerCommand::Stop {
84 graceful,
85 completion: Some(tx),
86 });
87 async move {
88 let _ = rx.await;
89 }
90 }
91}
92
93impl<T> Clone for Server<T> {
94 fn clone(&self) -> Self {
95 Self {
96 cmd: self.cmd.clone(),
97 shared: self.shared.clone(),
98 stop: None,
99 }
100 }
101}
102
103impl<T> Future for Server<T> {
104 type Output = io::Result<()>;
105
106 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
107 let this = self.get_mut();
108
109 if this.stop.is_none() {
110 let (tx, rx) = oneshot::async_channel();
111 if this.cmd.try_send(ServerCommand::NotifyStopped(tx)).is_err() {
112 return Poll::Ready(Ok(()));
113 }
114 this.stop = Some(rx);
115 }
116
117 let _ = ready!(Pin::new(this.stop.as_mut().unwrap()).poll(cx));
118
119 Poll::Ready(Ok(()))
120 }
121}