1use std::cell::RefCell;
11use std::future::Future;
12use std::rc::Rc;
13
14use futures::channel::oneshot;
15use futures::future::LocalBoxFuture;
16use futures::FutureExt;
17
18use crate::connection::{H2Connection, RequestInit, Response};
19use crate::errors::H2Error;
20
21pub trait PoolConnection {
24 fn is_closed(&self) -> bool;
26 fn can_open_stream(&self) -> bool;
29 fn request(&self, init: RequestInit) -> LocalBoxFuture<'static, Result<Response, H2Error>>;
31 fn close(&self);
33}
34
35impl PoolConnection for H2Connection {
36 fn is_closed(&self) -> bool {
37 H2Connection::is_closed(self)
38 }
39 fn can_open_stream(&self) -> bool {
40 H2Connection::can_open_stream(self)
41 }
42 fn request(&self, init: RequestInit) -> LocalBoxFuture<'static, Result<Response, H2Error>> {
43 let conn = self.clone();
44 async move { conn.request(init).await }.boxed_local()
45 }
46 fn close(&self) {
47 H2Connection::close(self)
48 }
49}
50
51type Factory = Rc<dyn Fn() -> LocalBoxFuture<'static, Result<Rc<dyn PoolConnection>, H2Error>>>;
52
53struct PoolState {
54 conns: Vec<Rc<dyn PoolConnection>>,
55 opening: bool,
58 open_waiters: Vec<oneshot::Sender<()>>,
59}
60
61#[derive(Clone)]
63pub struct H2Pool {
64 shared: Rc<RefCell<PoolState>>,
65 factory: Factory,
66 max_connections: usize,
67}
68
69impl H2Pool {
70 pub fn new<F, Fut>(factory: F, max_connections: usize) -> Self
75 where
76 F: Fn() -> Fut + 'static,
77 Fut: Future<Output = Result<Rc<dyn PoolConnection>, H2Error>> + 'static,
78 {
79 Self {
80 shared: Rc::new(RefCell::new(PoolState {
81 conns: Vec::new(),
82 opening: false,
83 open_waiters: Vec::new(),
84 })),
85 factory: Rc::new(move || factory().boxed_local()),
86 max_connections,
87 }
88 }
89
90 pub async fn request(&self, init: RequestInit) -> Result<Response, H2Error> {
93 let mut init = Some(init);
95 loop {
96 let chosen: Option<Rc<dyn PoolConnection>> = {
97 let mut st = self.shared.borrow_mut();
98 st.conns.retain(|c| !c.is_closed());
99 if let Some(c) = st.conns.iter().find(|c| c.can_open_stream()) {
100 Some(c.clone())
101 } else if !st.conns.is_empty() && st.conns.len() >= self.max_connections {
102 st.conns.first().cloned()
104 } else {
105 None
106 }
107 };
108 if let Some(conn) = chosen {
109 return conn.request(init.take().expect("request issued once")).await;
110 }
111
112 self.open_one().await?;
114
115 let fresh = self.shared.borrow().conns.last().cloned();
118 if let Some(conn) = fresh {
119 if !conn.is_closed() && !conn.can_open_stream() {
120 return conn.request(init.take().expect("request issued once")).await;
121 }
122 }
123 }
124 }
125
126 async fn open_one(&self) -> Result<(), H2Error> {
128 let wait = {
129 let mut st = self.shared.borrow_mut();
130 if st.opening {
131 let (tx, rx) = oneshot::channel();
132 st.open_waiters.push(tx);
133 Some(rx)
134 } else {
135 st.opening = true;
136 None
137 }
138 };
139 if let Some(rx) = wait {
140 let _ = rx.await; return Ok(());
142 }
143
144 let result = (self.factory)().await;
146 let mut st = self.shared.borrow_mut();
147 st.opening = false;
148 for tx in st.open_waiters.drain(..) {
149 let _ = tx.send(());
150 }
151 let conn = result?;
152 st.conns.push(conn);
153 Ok(())
154 }
155
156 pub fn connections(&self) -> usize {
158 self.shared
159 .borrow()
160 .conns
161 .iter()
162 .filter(|c| !c.is_closed())
163 .count()
164 }
165
166 pub fn close(&self) {
168 for conn in self.shared.borrow_mut().conns.drain(..) {
169 conn.close();
170 }
171 }
172}