1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-06-02 13:29:24 +00:00
actix-web/actix-http/src/client/pool.rs

646 lines
18 KiB
Rust
Raw Normal View History

2018-11-12 07:12:54 +00:00
use std::cell::RefCell;
2019-01-27 19:40:26 +00:00
use std::collections::VecDeque;
use std::future::Future;
use std::pin::Pin;
2020-08-09 20:49:43 +00:00
use std::rc::Rc;
use std::task::{Context, Poll};
2018-11-12 07:12:54 +00:00
use std::time::{Duration, Instant};
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
use actix_rt::time::{sleep, Sleep};
2018-12-11 02:08:33 +00:00
use actix_service::Service;
use actix_utils::task::LocalWaker;
2021-01-15 02:11:10 +00:00
use ahash::AHashMap;
2019-01-29 04:41:09 +00:00
use bytes::Bytes;
use futures_channel::oneshot;
use futures_core::future::LocalBoxFuture;
use futures_util::future::{poll_fn, FutureExt};
use h2::client::{Connection, SendRequest};
use http::uri::Authority;
2018-11-12 07:12:54 +00:00
use indexmap::IndexSet;
use pin_project::pin_project;
2020-02-27 02:10:55 +00:00
use slab::Slab;
2018-11-12 07:12:54 +00:00
use super::config::ConnectorConfig;
2019-01-29 04:41:09 +00:00
use super::connection::{ConnectionType, IoConnection};
2019-03-13 21:41:40 +00:00
use super::error::ConnectError;
use super::h2proto::handshake;
use super::Connect;
2021-02-07 03:51:36 +00:00
use crate::client::connection::H2Connection;
2018-11-12 07:12:54 +00:00
2019-01-29 04:41:09 +00:00
#[derive(Clone, Copy, PartialEq)]
2019-04-08 18:09:57 +00:00
/// Protocol version
2019-01-29 04:41:09 +00:00
pub enum Protocol {
Http1,
Http2,
}
2018-11-12 07:12:54 +00:00
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
pub(crate) struct Key {
authority: Authority,
}
impl From<Authority> for Key {
fn from(authority: Authority) -> Key {
Key { authority }
}
}
/// Connections pool
pub(crate) struct ConnectionPool<T, Io: 'static>(Rc<T>, Rc<RefCell<Inner<Io>>>);
2018-11-12 07:12:54 +00:00
impl<T, Io> ConnectionPool<T, Io>
where
2019-11-19 12:54:19 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
2018-11-12 07:12:54 +00:00
{
pub(crate) fn new(connector: T, config: ConnectorConfig) -> Self {
let connector_rc = Rc::new(connector);
let inner_rc = Rc::new(RefCell::new(Inner {
config,
acquired: 0,
waiters: Slab::new(),
waiters_queue: IndexSet::new(),
2021-01-15 02:11:10 +00:00
available: AHashMap::default(),
waker: LocalWaker::new(),
}));
// start support future
actix_rt::spawn(ConnectorPoolSupport {
2020-08-09 20:49:43 +00:00
connector: Rc::clone(&connector_rc),
inner: Rc::clone(&inner_rc),
});
ConnectionPool(connector_rc, inner_rc)
2018-11-12 07:12:54 +00:00
}
}
impl<T, Io> Clone for ConnectionPool<T, Io>
where
2019-11-18 12:42:27 +00:00
Io: 'static,
2018-11-12 07:12:54 +00:00
{
fn clone(&self) -> Self {
ConnectionPool(self.0.clone(), self.1.clone())
}
}
2020-08-09 20:49:43 +00:00
impl<T, Io> Drop for ConnectionPool<T, Io> {
fn drop(&mut self) {
// wake up the ConnectorPoolSupport when dropping so it can exit properly.
self.1.borrow().waker.wake();
}
}
impl<T, Io> Service<Connect> for ConnectionPool<T, Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Connect, Response = (Io, Protocol), Error = ConnectError> + 'static,
2018-11-12 07:12:54 +00:00
{
2018-11-15 19:10:23 +00:00
type Response = IoConnection<Io>;
2019-03-13 21:41:40 +00:00
type Error = ConnectError;
2019-11-18 12:42:27 +00:00
type Future = LocalBoxFuture<'static, Result<IoConnection<Io>, ConnectError>>;
2018-11-12 07:12:54 +00:00
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
2019-11-18 12:42:27 +00:00
self.0.poll_ready(cx)
2018-11-12 07:12:54 +00:00
}
fn call(&self, req: Connect) -> Self::Future {
let connector = self.0.clone();
2019-11-18 12:42:27 +00:00
let inner = self.1.clone();
let fut = async move {
2019-12-05 17:35:43 +00:00
let key = if let Some(authority) = req.uri.authority() {
2019-11-18 12:42:27 +00:00
authority.clone().into()
} else {
return Err(ConnectError::Unresolved);
2019-11-18 12:42:27 +00:00
};
2018-11-12 07:12:54 +00:00
2019-11-18 12:42:27 +00:00
// acquire connection
match poll_fn(|cx| Poll::Ready(inner.borrow_mut().acquire(&key, cx))).await {
Acquire::Acquired(io, created) => {
// use existing connection
2020-09-10 13:46:35 +00:00
Ok(IoConnection::new(
2019-11-18 12:42:27 +00:00
io,
created,
Some(Acquired(key, Some(inner))),
2020-09-10 13:46:35 +00:00
))
2019-11-18 12:42:27 +00:00
}
Acquire::Available => {
// open tcp connection
let (io, proto) = connector.call(req).await?;
let config = inner.borrow().config.clone();
2019-11-18 12:42:27 +00:00
let guard = OpenGuard::new(key, inner);
if proto == Protocol::Http1 {
Ok(IoConnection::new(
ConnectionType::H1(io),
Instant::now(),
Some(guard.consume()),
))
} else {
2021-02-07 03:51:36 +00:00
let (sender, connection) = handshake(io, &config).await?;
2019-11-18 12:42:27 +00:00
Ok(IoConnection::new(
2021-02-07 03:51:36 +00:00
ConnectionType::H2(H2Connection::new(sender, connection)),
2019-11-18 12:42:27 +00:00
Instant::now(),
Some(guard.consume()),
))
}
}
_ => {
// connection is not available, wait
let (rx, token) = inner.borrow_mut().wait_for(req);
let guard = WaiterGuard::new(key, token, inner);
let res = match rx.await {
Err(_) => Err(ConnectError::Disconnected),
Ok(res) => res,
};
guard.consume();
res
}
2018-11-12 07:12:54 +00:00
}
2019-11-18 12:42:27 +00:00
};
2019-11-18 12:42:27 +00:00
fut.boxed_local()
2018-11-12 07:12:54 +00:00
}
}
2019-11-18 12:42:27 +00:00
struct WaiterGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
key: Key,
token: usize,
inner: Option<Rc<RefCell<Inner<Io>>>>,
}
2019-11-18 12:42:27 +00:00
impl<Io> WaiterGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
2019-11-18 12:42:27 +00:00
fn new(key: Key, token: usize, inner: Rc<RefCell<Inner<Io>>>) -> Self {
Self {
key,
token,
inner: Some(inner),
2018-11-12 07:12:54 +00:00
}
}
2019-11-18 12:42:27 +00:00
fn consume(mut self) {
let _ = self.inner.take();
}
2018-11-12 07:12:54 +00:00
}
2019-11-18 12:42:27 +00:00
impl<Io> Drop for WaiterGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
2019-11-18 12:42:27 +00:00
fn drop(&mut self) {
if let Some(i) = self.inner.take() {
let mut inner = i.as_ref().borrow_mut();
inner.release_waiter(&self.key, self.token);
inner.check_availability();
2018-11-12 07:12:54 +00:00
}
}
}
2019-11-18 12:42:27 +00:00
struct OpenGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
key: Key,
inner: Option<Rc<RefCell<Inner<Io>>>>,
}
2019-11-18 12:42:27 +00:00
impl<Io> OpenGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
2019-11-18 12:42:27 +00:00
fn new(key: Key, inner: Rc<RefCell<Inner<Io>>>) -> Self {
Self {
2018-11-12 07:12:54 +00:00
key,
inner: Some(inner),
}
}
2019-11-18 12:42:27 +00:00
fn consume(mut self) -> Acquired<Io> {
Acquired(self.key.clone(), self.inner.take())
}
2018-11-12 07:12:54 +00:00
}
2019-11-18 12:42:27 +00:00
impl<Io> Drop for OpenGuard<Io>
2018-11-12 07:12:54 +00:00
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
fn drop(&mut self) {
2019-11-18 12:42:27 +00:00
if let Some(i) = self.inner.take() {
let mut inner = i.as_ref().borrow_mut();
2018-11-12 07:12:54 +00:00
inner.release();
inner.check_availability();
2018-11-12 07:12:54 +00:00
}
}
}
enum Acquire<T> {
2019-01-29 04:41:09 +00:00
Acquired(ConnectionType<T>, Instant),
2018-11-12 07:12:54 +00:00
Available,
NotAvailable,
}
2019-01-29 04:41:09 +00:00
struct AvailableConnection<Io> {
io: ConnectionType<Io>,
used: Instant,
created: Instant,
}
2018-11-14 06:53:30 +00:00
pub(crate) struct Inner<Io> {
config: ConnectorConfig,
2018-11-12 07:12:54 +00:00
acquired: usize,
2021-01-15 02:11:10 +00:00
available: AHashMap<Key, VecDeque<AvailableConnection<Io>>>,
2019-07-30 15:00:46 +00:00
waiters: Slab<
Option<(
Connect,
oneshot::Sender<Result<IoConnection<Io>, ConnectError>>,
)>,
>,
2018-11-12 07:12:54 +00:00
waiters_queue: IndexSet<(Key, usize)>,
2019-11-18 12:42:27 +00:00
waker: LocalWaker,
2018-11-12 07:12:54 +00:00
}
2018-11-14 06:53:30 +00:00
impl<Io> Inner<Io> {
fn reserve(&mut self) {
self.acquired += 1;
}
fn release(&mut self) {
self.acquired -= 1;
}
fn release_waiter(&mut self, key: &Key, token: usize) {
self.waiters.remove(token);
2019-09-12 15:52:46 +00:00
let _ = self.waiters_queue.shift_remove(&(key.clone(), token));
2018-11-14 06:53:30 +00:00
}
}
2018-11-12 07:12:54 +00:00
impl<Io> Inner<Io>
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
/// connection is not available, wait
fn wait_for(
&mut self,
connect: Connect,
2018-11-12 07:12:54 +00:00
) -> (
2019-03-13 21:41:40 +00:00
oneshot::Receiver<Result<IoConnection<Io>, ConnectError>>,
2018-11-12 07:12:54 +00:00
usize,
) {
let (tx, rx) = oneshot::channel();
2019-12-05 17:35:43 +00:00
let key: Key = connect.uri.authority().unwrap().clone().into();
2018-11-12 07:12:54 +00:00
let entry = self.waiters.vacant_entry();
let token = entry.key();
2019-07-30 15:00:46 +00:00
entry.insert(Some((connect, tx)));
assert!(self.waiters_queue.insert((key, token)));
2019-11-18 12:42:27 +00:00
(rx, token)
2018-11-12 07:12:54 +00:00
}
2019-12-07 18:46:51 +00:00
fn acquire(&mut self, key: &Key, cx: &mut Context<'_>) -> Acquire<Io> {
2018-11-12 07:12:54 +00:00
// check limits
if self.config.limit > 0 && self.acquired >= self.config.limit {
2018-11-12 07:12:54 +00:00
return Acquire::NotAvailable;
}
self.reserve();
// check if open connection is available
// cleanup stale connections at the same time
if let Some(ref mut connections) = self.available.get_mut(key) {
let now = Instant::now();
while let Some(conn) = connections.pop_back() {
// check if it still usable
if (now - conn.used) > self.config.conn_keep_alive
|| (now - conn.created) > self.config.conn_lifetime
2018-11-12 07:12:54 +00:00
{
if let Some(timeout) = self.config.disconnect_timeout {
2019-01-29 04:41:09 +00:00
if let ConnectionType::H1(io) = conn.io {
actix_rt::spawn(CloseConnection::new(io, timeout));
2019-01-29 04:41:09 +00:00
}
2018-11-12 07:12:54 +00:00
}
} else {
let mut io = conn.io;
let mut buf = [0; 2];
let mut read_buf = ReadBuf::new(&mut buf);
2019-01-29 04:41:09 +00:00
if let ConnectionType::H1(ref mut s) = io {
match Pin::new(s).poll_read(cx, &mut read_buf) {
2021-01-04 01:01:35 +00:00
Poll::Pending => {}
Poll::Ready(Ok(())) if !read_buf.filled().is_empty() => {
if let Some(timeout) = self.config.disconnect_timeout {
2019-01-29 04:41:09 +00:00
if let ConnectionType::H1(io) = io {
2019-11-26 05:25:50 +00:00
actix_rt::spawn(CloseConnection::new(
io, timeout,
));
2019-01-29 04:41:09 +00:00
}
}
continue;
2018-11-12 07:12:54 +00:00
}
2019-11-18 12:42:27 +00:00
_ => continue,
2018-11-12 07:12:54 +00:00
}
}
return Acquire::Acquired(io, conn.created);
}
}
}
Acquire::Available
}
fn release_conn(&mut self, key: &Key, io: ConnectionType<Io>, created: Instant) {
self.acquired -= 1;
self.available
.entry(key.clone())
.or_insert_with(VecDeque::new)
.push_back(AvailableConnection {
io,
created,
used: Instant::now(),
});
self.check_availability();
}
2019-01-29 04:41:09 +00:00
fn release_close(&mut self, io: ConnectionType<Io>) {
2018-11-12 07:12:54 +00:00
self.acquired -= 1;
if let Some(timeout) = self.config.disconnect_timeout {
2019-01-29 04:41:09 +00:00
if let ConnectionType::H1(io) = io {
actix_rt::spawn(CloseConnection::new(io, timeout));
2019-01-29 04:41:09 +00:00
}
2018-11-12 07:12:54 +00:00
}
self.check_availability();
2018-11-12 07:12:54 +00:00
}
fn check_availability(&self) {
if !self.waiters_queue.is_empty() && self.acquired < self.config.limit {
2019-11-18 12:42:27 +00:00
self.waker.wake();
2018-11-12 07:12:54 +00:00
}
}
}
#[pin_project::pin_project]
2018-11-12 07:12:54 +00:00
struct CloseConnection<T> {
io: T,
#[pin]
timeout: Sleep,
2018-11-12 07:12:54 +00:00
}
impl<T> CloseConnection<T>
where
2019-11-19 12:54:19 +00:00
T: AsyncWrite + Unpin,
2018-11-12 07:12:54 +00:00
{
fn new(io: T, timeout: Duration) -> Self {
CloseConnection {
io,
timeout: sleep(timeout),
2018-11-12 07:12:54 +00:00
}
}
}
impl<T> Future for CloseConnection<T>
where
2019-11-18 12:42:27 +00:00
T: AsyncWrite + Unpin,
2018-11-12 07:12:54 +00:00
{
2019-11-18 12:42:27 +00:00
type Output = ();
2019-12-07 18:46:51 +00:00
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
let this = self.project();
2019-11-19 12:54:19 +00:00
match this.timeout.poll(cx) {
2019-11-18 12:42:27 +00:00
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => match Pin::new(this.io).poll_shutdown(cx) {
2019-11-18 12:42:27 +00:00
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => Poll::Pending,
2018-11-12 07:12:54 +00:00
},
}
}
}
#[pin_project]
struct ConnectorPoolSupport<T, Io>
where
2019-11-19 12:54:19 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
connector: Rc<T>,
2020-08-09 20:49:43 +00:00
inner: Rc<RefCell<Inner<Io>>>,
}
impl<T, Io> Future for ConnectorPoolSupport<T, Io>
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
T: Service<Connect, Response = (Io, Protocol), Error = ConnectError>,
2019-11-19 12:54:19 +00:00
T::Future: 'static,
{
2019-11-18 12:42:27 +00:00
type Output = ();
2019-12-07 18:46:51 +00:00
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
2020-08-09 20:49:43 +00:00
if Rc::strong_count(this.inner) == 1 {
// If we are last copy of Inner<Io> it means the ConnectionPool is already gone
// and we are safe to exit.
return Poll::Ready(());
}
let mut inner = this.inner.borrow_mut();
inner.waker.register(cx.waker());
2020-08-09 20:49:43 +00:00
// check waiters
loop {
let (key, token) = {
if let Some((key, token)) = inner.waiters_queue.get_index(0) {
(key.clone(), *token)
} else {
break;
}
2020-08-09 20:49:43 +00:00
};
if inner.waiters.get(token).unwrap().is_none() {
continue;
}
2019-07-30 15:00:46 +00:00
2020-08-09 20:49:43 +00:00
match inner.acquire(&key, cx) {
Acquire::NotAvailable => break,
Acquire::Acquired(io, created) => {
let tx = inner.waiters.get_mut(token).unwrap().take().unwrap().1;
if let Err(conn) = tx.send(Ok(IoConnection::new(
io,
created,
Some(Acquired(key.clone(), Some(this.inner.clone()))),
))) {
let (io, created) = conn.unwrap().into_inner();
inner.release_conn(&key, io, created);
}
}
2020-08-09 20:49:43 +00:00
Acquire::Available => {
let (connect, tx) =
inner.waiters.get_mut(token).unwrap().take().unwrap();
OpenWaitingConnection::spawn(
key.clone(),
tx,
this.inner.clone(),
this.connector.call(connect),
inner.config.clone(),
);
}
}
2020-08-09 20:49:43 +00:00
let _ = inner.waiters_queue.swap_remove_index(0);
}
2020-08-09 20:49:43 +00:00
Poll::Pending
}
}
#[pin_project::pin_project(PinnedDrop)]
struct OpenWaitingConnection<F, Io>
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
#[pin]
fut: F,
key: Key,
2019-11-18 12:42:27 +00:00
h2: Option<
LocalBoxFuture<
'static,
Result<(SendRequest<Bytes>, Connection<Io, Bytes>), h2::Error>,
>,
>,
rx: Option<oneshot::Sender<Result<IoConnection<Io>, ConnectError>>>,
inner: Option<Rc<RefCell<Inner<Io>>>>,
config: ConnectorConfig,
}
impl<F, Io> OpenWaitingConnection<F, Io>
where
2019-11-19 12:54:19 +00:00
F: Future<Output = Result<(Io, Protocol), ConnectError>> + 'static,
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
fn spawn(
key: Key,
rx: oneshot::Sender<Result<IoConnection<Io>, ConnectError>>,
inner: Rc<RefCell<Inner<Io>>>,
fut: F,
config: ConnectorConfig,
) {
2019-11-26 05:25:50 +00:00
actix_rt::spawn(OpenWaitingConnection {
key,
fut,
h2: None,
rx: Some(rx),
inner: Some(inner),
config,
});
}
}
#[pin_project::pinned_drop]
impl<F, Io> PinnedDrop for OpenWaitingConnection<F, Io>
where
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin + 'static,
{
fn drop(self: Pin<&mut Self>) {
if let Some(inner) = self.project().inner.take() {
let mut inner = inner.as_ref().borrow_mut();
inner.release();
inner.check_availability();
}
}
}
impl<F, Io> Future for OpenWaitingConnection<F, Io>
where
2019-11-19 12:54:19 +00:00
F: Future<Output = Result<(Io, Protocol), ConnectError>>,
2019-11-18 12:42:27 +00:00
Io: AsyncRead + AsyncWrite + Unpin,
{
2019-11-18 12:42:27 +00:00
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.as_mut().project();
2019-11-18 12:42:27 +00:00
if let Some(ref mut h2) = this.h2 {
return match Pin::new(h2).poll(cx) {
2021-02-07 03:51:36 +00:00
Poll::Ready(Ok((sender, connection))) => {
2019-11-18 12:42:27 +00:00
let rx = this.rx.take().unwrap();
let _ = rx.send(Ok(IoConnection::new(
2021-02-07 03:51:36 +00:00
ConnectionType::H2(H2Connection::new(sender, connection)),
Instant::now(),
2019-11-18 12:42:27 +00:00
Some(Acquired(this.key.clone(), this.inner.take())),
)));
2019-11-18 12:42:27 +00:00
Poll::Ready(())
}
2019-11-18 12:42:27 +00:00
Poll::Pending => Poll::Pending,
Poll::Ready(Err(err)) => {
let _ = this.inner.take();
if let Some(rx) = this.rx.take() {
let _ = rx.send(Err(ConnectError::H2(err)));
}
2019-11-18 12:42:27 +00:00
Poll::Ready(())
}
};
}
match this.fut.poll(cx) {
2019-11-18 12:42:27 +00:00
Poll::Ready(Err(err)) => {
let _ = this.inner.take();
if let Some(rx) = this.rx.take() {
let _ = rx.send(Err(err));
}
2019-11-18 12:42:27 +00:00
Poll::Ready(())
}
2019-11-18 12:42:27 +00:00
Poll::Ready(Ok((io, proto))) => {
if proto == Protocol::Http1 {
2019-11-18 12:42:27 +00:00
let rx = this.rx.take().unwrap();
let _ = rx.send(Ok(IoConnection::new(
ConnectionType::H1(io),
Instant::now(),
2019-11-18 12:42:27 +00:00
Some(Acquired(this.key.clone(), this.inner.take())),
)));
2019-11-18 12:42:27 +00:00
Poll::Ready(())
} else {
*this.h2 = Some(handshake(io, this.config).boxed_local());
self.poll(cx)
}
}
2019-11-18 12:42:27 +00:00
Poll::Pending => Poll::Pending,
}
}
}
2018-11-14 06:53:30 +00:00
pub(crate) struct Acquired<T>(Key, Option<Rc<RefCell<Inner<T>>>>);
2018-11-12 07:12:54 +00:00
impl<T> Acquired<T>
where
2019-11-18 12:42:27 +00:00
T: AsyncRead + AsyncWrite + Unpin + 'static,
2018-11-12 07:12:54 +00:00
{
2018-11-15 19:10:23 +00:00
pub(crate) fn close(&mut self, conn: IoConnection<T>) {
2018-11-12 07:12:54 +00:00
if let Some(inner) = self.1.take() {
let (io, _) = conn.into_inner();
inner.as_ref().borrow_mut().release_close(io);
}
}
2018-11-15 19:10:23 +00:00
pub(crate) fn release(&mut self, conn: IoConnection<T>) {
2018-11-12 07:12:54 +00:00
if let Some(inner) = self.1.take() {
let (io, created) = conn.into_inner();
inner
.as_ref()
.borrow_mut()
.release_conn(&self.0, io, created);
}
}
}
2018-11-14 06:53:30 +00:00
impl<T> Drop for Acquired<T> {
2018-11-12 07:12:54 +00:00
fn drop(&mut self) {
if let Some(inner) = self.1.take() {
inner.as_ref().borrow_mut().release();
}
}
}