tower_limit/concurrency/
future.rs

1//! Future types
2//!
3use super::sync::semaphore::Semaphore;
4use futures_core::ready;
5use pin_project::{pin_project, pinned_drop};
6use std::sync::Arc;
7use std::{
8    future::Future,
9    pin::Pin,
10    task::{Context, Poll},
11};
12
13/// Future for the `ConcurrencyLimit` service.
14#[pin_project(PinnedDrop)]
15#[derive(Debug)]
16pub struct ResponseFuture<T> {
17    #[pin]
18    inner: T,
19    semaphore: Arc<Semaphore>,
20}
21
22impl<T> ResponseFuture<T> {
23    pub(crate) fn new(inner: T, semaphore: Arc<Semaphore>) -> ResponseFuture<T> {
24        ResponseFuture { inner, semaphore }
25    }
26}
27
28impl<F, T, E> Future for ResponseFuture<F>
29where
30    F: Future<Output = Result<T, E>>,
31{
32    type Output = Result<T, E>;
33
34    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
35        Poll::Ready(ready!(self.project().inner.poll(cx)))
36    }
37}
38
39#[pinned_drop]
40impl<T> PinnedDrop for ResponseFuture<T> {
41    fn drop(self: Pin<&mut Self>) {
42        self.project().semaphore.add_permits(1);
43    }
44}