1 //! General purpose TCP server.
2
3 #![deny(rust_2018_idioms, nonstandard_style)]
4 #![doc(html_logo_url = "https://actix.rs/img/logo.png")]
5 #![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
6
7 mod accept;
8 mod builder;
9 mod config;
10 mod server;
11 mod service;
12 mod signals;
13 mod socket;
14 mod test_server;
15 mod waker_queue;
16 mod worker;
17
18 pub use self::builder::ServerBuilder;
19 pub use self::config::{ServiceConfig, ServiceRuntime};
20 pub use self::server::Server;
21 pub use self::service::ServiceFactory;
22 pub use self::test_server::TestServer;
23
24 #[doc(hidden)]
25 pub use self::socket::FromStream;
26
27 use std::future::Future;
28 use std::pin::Pin;
29 use std::task::{Context, Poll};
30
31 /// Socket ID token
32 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
33 pub(crate) struct Token(usize);
34
35 impl Default for Token {
default() -> Self36 fn default() -> Self {
37 Self::new()
38 }
39 }
40
41 impl Token {
new() -> Self42 fn new() -> Self {
43 Self(0)
44 }
45
next(&mut self) -> Token46 pub(crate) fn next(&mut self) -> Token {
47 let token = Token(self.0);
48 self.0 += 1;
49 token
50 }
51 }
52
53 /// Start server building process
new() -> ServerBuilder54 pub fn new() -> ServerBuilder {
55 ServerBuilder::default()
56 }
57
58 // a poor man's join future. joined future is only used when starting/stopping the server.
59 // pin_project and pinned futures are overkill for this task.
60 pub(crate) struct JoinAll<T> {
61 fut: Vec<JoinFuture<T>>,
62 }
63
join_all<T>(fut: Vec<impl Future<Output = T> + 'static>) -> JoinAll<T>64 pub(crate) fn join_all<T>(fut: Vec<impl Future<Output = T> + 'static>) -> JoinAll<T> {
65 let fut = fut
66 .into_iter()
67 .map(|f| JoinFuture::Future(Box::pin(f)))
68 .collect();
69
70 JoinAll { fut }
71 }
72
73 enum JoinFuture<T> {
74 Future(Pin<Box<dyn Future<Output = T>>>),
75 Result(Option<T>),
76 }
77
78 impl<T> Unpin for JoinAll<T> {}
79
80 impl<T> Future for JoinAll<T> {
81 type Output = Vec<T>;
82
poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>83 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
84 let mut ready = true;
85
86 let this = self.get_mut();
87 for fut in this.fut.iter_mut() {
88 if let JoinFuture::Future(f) = fut {
89 match f.as_mut().poll(cx) {
90 Poll::Ready(t) => {
91 *fut = JoinFuture::Result(Some(t));
92 }
93 Poll::Pending => ready = false,
94 }
95 }
96 }
97
98 if ready {
99 let mut res = Vec::new();
100 for fut in this.fut.iter_mut() {
101 if let JoinFuture::Result(f) = fut {
102 res.push(f.take().unwrap());
103 }
104 }
105
106 Poll::Ready(res)
107 } else {
108 Poll::Pending
109 }
110 }
111 }
112
113 #[cfg(test)]
114 mod test {
115 use super::*;
116
117 use actix_utils::future::ready;
118
119 #[actix_rt::test]
test_join_all()120 async fn test_join_all() {
121 let futs = vec![ready(Ok(1)), ready(Err(3)), ready(Ok(9))];
122 let mut res = join_all(futs).await.into_iter();
123 assert_eq!(Ok(1), res.next().unwrap());
124 assert_eq!(Err(3), res.next().unwrap());
125 assert_eq!(Ok(9), res.next().unwrap());
126 }
127 }
128