use std::future::Future;
use std::pin::Pin;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::task::{Context, Poll};
use hyper::Uri;
use tower_service::Service;
#[derive(Clone)]
pub(crate) struct CountingConnector<C> {
inner: C,
opens: Arc<AtomicU64>,
}
impl<C> CountingConnector<C> {
pub(crate) fn new(inner: C, opens: Arc<AtomicU64>) -> Self {
Self { inner, opens }
}
}
impl<C> Service<Uri> for CountingConnector<C>
where
C: Service<Uri>,
C::Future: Send + 'static,
{
type Response = C::Response;
type Error = C::Error;
type Future = Pin<Box<dyn Future<Output = Result<C::Response, C::Error>> + Send>>;
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.inner.poll_ready(cx)
}
fn call(&mut self, dst: Uri) -> Self::Future {
self.opens.fetch_add(1, Ordering::Relaxed);
Box::pin(self.inner.call(dst))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct PoolStats {
pub opened: u64,
pub dispatched: u64,
}
impl PoolStats {
#[must_use]
pub fn reused(&self) -> u64 {
self.dispatched.saturating_sub(self.opened)
}
}