1pub use self::internal::builder;
9
10#[cfg(docsrs)]
11pub use self::internal::Builder;
12#[cfg(docsrs)]
13pub use self::internal::Cache;
14#[cfg(docsrs)]
15pub use self::internal::Cached;
16
17mod internal {
21 use std::collections::VecDeque;
22 use std::fmt;
23 use std::pin::Pin;
24 use std::sync::{Arc, Mutex, Weak};
25 use std::task::{self, Poll, Waker, ready};
26
27 use tower_service::Service;
28
29 use super::events;
30
31 pub fn builder() -> Builder<events::Ignore> {
33 Builder {
34 events: events::Ignore,
35 }
36 }
37
38 #[derive(Debug)]
48 pub struct Cache<M, Dst, Ev>
49 where
50 M: Service<Dst>,
51 {
52 connector: M,
53 shared: Arc<Mutex<Shared<M::Response>>>,
54 events: Ev,
55 ready: Ready<M::Response>,
56 ready_waiter: Option<WaiterId>,
57 }
58
59 #[derive(Debug)]
67 pub struct Builder<Ev> {
68 events: Ev,
69 }
70
71 pub struct Cached<S> {
82 is_closed: bool,
83 inner: Option<S>,
84 shared: Weak<Mutex<Shared<S>>>,
85 }
87
88 #[derive(Debug)]
89 enum Ready<S> {
90 None,
91 Cached(S),
92 }
93
94 pub enum CacheFuture<M, Dst, Ev>
95 where
96 M: Service<Dst>,
97 {
98 Racing {
99 shared: Arc<Mutex<Shared<M::Response>>>,
100 waiter: WaiterId,
101 future: Option<M::Future>,
102 events: Ev,
103 },
104 Cached {
105 svc: Option<Cached<M::Response>>,
106 },
107 }
108
109 #[derive(Debug)]
111 pub struct Shared<S> {
112 services: Vec<S>,
113 waiters: VecDeque<Waiter>,
114 reservations: Vec<(WaiterId, S)>,
115 next_waiter: usize,
116 }
117
118 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
119 pub struct WaiterId(usize);
120
121 #[derive(Debug)]
122 struct Waiter {
123 id: WaiterId,
124 waker: Option<Waker>,
125 }
126
127 impl<Ev> Builder<Ev> {
130 pub fn executor<E>(self, exec: E) -> Builder<events::WithExecutor<E>> {
150 Builder {
151 events: events::WithExecutor(exec),
152 }
153 }
154
155 pub fn build<M, Dst>(self, connector: M) -> Cache<M, Dst, Ev>
157 where
158 M: Service<Dst>,
159 {
160 Cache {
161 connector,
162 events: self.events,
163 ready: Ready::None,
164 ready_waiter: None,
165 shared: Arc::new(Mutex::new(Shared {
166 services: Vec::new(),
167 waiters: VecDeque::new(),
168 reservations: Vec::new(),
169 next_waiter: 0,
170 })),
171 }
172 }
173 }
174
175 impl<M, Dst, Ev> Cache<M, Dst, Ev>
178 where
179 M: Service<Dst>,
180 {
181 pub fn retain<F>(&mut self, predicate: F)
183 where
184 F: FnMut(&mut M::Response) -> bool,
185 {
186 let mut predicate = predicate;
187 if let Ready::Cached(svc) = &mut self.ready {
188 if !predicate(svc) {
189 self.ready = Ready::None;
190 }
191 }
192
193 self.shared.lock().unwrap().services.retain_mut(predicate);
194 }
195
196 pub fn is_empty(&self) -> bool {
198 matches!(self.ready, Ready::None) && self.shared.lock().unwrap().services.is_empty()
199 }
200 }
201
202 impl<M, Dst, Ev> Service<Dst> for Cache<M, Dst, Ev>
203 where
204 M: Service<Dst>,
205 M::Future: Unpin,
206 M::Response: Unpin,
207 Ev: events::Events<BackgroundConnect<M::Future, M::Response>> + Clone + Unpin,
208 {
209 type Response = Cached<M::Response>;
210 type Error = M::Error;
211 type Future = CacheFuture<M, Dst, Ev>;
212
213 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
214 match self.ready {
215 Ready::Cached(_) => return Poll::Ready(Ok(())),
216 Ready::None => {}
217 }
218
219 {
220 let mut shared = self.shared.lock().unwrap();
221 if let Some(id) = self.ready_waiter {
222 if let Some(svc) = shared.take_reserved(id) {
223 self.ready_waiter = None;
224 self.ready = Ready::Cached(svc);
225 return Poll::Ready(Ok(()));
226 }
227 } else if let Some(svc) = shared.take_available() {
228 self.ready = Ready::Cached(svc);
229 return Poll::Ready(Ok(()));
230 }
231
232 let id = *self
233 .ready_waiter
234 .get_or_insert_with(|| shared.push_waiter());
235 shared.store_waker(id, cx.waker());
236 }
237
238 match self.connector.poll_ready(cx) {
239 Poll::Ready(result) => {
240 if let Some(id) = self.ready_waiter.take() {
241 self.shared.lock().unwrap().cancel_waiter(id);
242 }
243 Poll::Ready(result)
244 }
245 Poll::Pending => Poll::Pending,
246 }
247 }
248
249 fn call(&mut self, target: Dst) -> Self::Future {
250 match std::mem::replace(&mut self.ready, Ready::None) {
252 Ready::Cached(svc) => {
253 return CacheFuture::Cached {
254 svc: Some(Cached::new(svc, Arc::downgrade(&self.shared))),
255 };
256 }
257 Ready::None => {
258 if let Some(id) = self.ready_waiter.take() {
259 let mut shared = self.shared.lock().unwrap();
260 if let Some(svc) = shared.take_reserved(id) {
261 return CacheFuture::Cached {
262 svc: Some(Cached::new(svc, Arc::downgrade(&self.shared))),
263 };
264 }
265 shared.cancel_waiter(id);
266 }
267 if let Some(svc) = self.shared.lock().unwrap().take_available() {
268 return CacheFuture::Cached {
269 svc: Some(Cached::new(svc, Arc::downgrade(&self.shared))),
270 };
271 }
272 }
273 }
274
275 let waiter = {
276 let mut locked = self.shared.lock().unwrap();
277 locked.push_waiter()
278 };
279
280 CacheFuture::Racing {
283 shared: self.shared.clone(),
284 waiter,
285 future: Some(self.connector.call(target)),
286 events: self.events.clone(),
287 }
288 }
289 }
290
291 impl<M, Dst, Ev> Clone for Cache<M, Dst, Ev>
292 where
293 M: Service<Dst> + Clone,
294 Ev: Clone,
295 {
296 fn clone(&self) -> Self {
297 Self {
298 connector: self.connector.clone(),
299 events: self.events.clone(),
300 shared: self.shared.clone(),
301 ready: Ready::None,
302 ready_waiter: None,
303 }
304 }
305 }
306
307 impl<M, Dst, Ev> Drop for Cache<M, Dst, Ev>
308 where
309 M: Service<Dst>,
310 {
311 fn drop(&mut self) {
312 if let Ready::Cached(svc) = std::mem::replace(&mut self.ready, Ready::None) {
313 if let Ok(mut shared) = self.shared.lock() {
314 shared.put(svc);
315 }
316 }
317 if let Some(id) = self.ready_waiter.take() {
318 if let Ok(mut shared) = self.shared.lock() {
319 shared.cancel_waiter(id);
320 }
321 }
322 }
323 }
324
325 impl<M, Dst, Ev> Drop for CacheFuture<M, Dst, Ev>
326 where
327 M: Service<Dst>,
328 {
329 fn drop(&mut self) {
330 if let CacheFuture::Racing { shared, waiter, .. } = self {
331 if let Ok(mut shared) = shared.lock() {
332 shared.cancel_waiter(*waiter);
333 }
334 }
335 }
336 }
337
338 impl<M, Dst, Ev> Future for CacheFuture<M, Dst, Ev>
339 where
340 M: Service<Dst>,
341 M::Future: Unpin,
342 M::Response: Unpin,
343 Ev: events::Events<BackgroundConnect<M::Future, M::Response>> + Unpin,
344 {
345 type Output = Result<Cached<M::Response>, M::Error>;
346
347 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
348 match &mut *self.as_mut() {
349 CacheFuture::Racing {
350 shared,
351 waiter,
352 future,
353 events,
354 } => {
355 {
356 let mut locked = shared.lock().unwrap();
357 if let Some(pool_got) = locked.take_reserved(*waiter) {
358 events.on_race_lost(BackgroundConnect {
359 future: future.take().expect("racing future polled after done"),
360 shared: Arc::downgrade(&shared),
361 });
362 return Poll::Ready(Ok(Cached::new(pool_got, Arc::downgrade(&shared))));
363 }
364 locked.store_waker(*waiter, cx.waker());
365 }
366
367 let connected = match ready!(
368 Pin::new(future.as_mut().expect("racing future polled after done"))
369 .poll(cx)
370 ) {
371 Ok(inner) => inner,
372 Err(err) => {
373 shared.lock().unwrap().cancel_waiter(*waiter);
374 return Poll::Ready(Err(err));
375 }
376 };
377
378 shared.lock().unwrap().cancel_waiter(*waiter);
379 Poll::Ready(Ok(Cached::new(connected, Arc::downgrade(&shared))))
380 }
381 CacheFuture::Cached { svc } => Poll::Ready(Ok(svc.take().unwrap())),
382 }
383 }
384 }
385
386 impl<S> Cached<S> {
389 fn new(inner: S, shared: Weak<Mutex<Shared<S>>>) -> Self {
390 Cached {
391 is_closed: false,
392 inner: Some(inner),
393 shared,
394 }
395 }
396
397 pub fn inner(&self) -> &S {
401 self.inner.as_ref().expect("inner only taken in drop")
402 }
403
404 pub fn inner_mut(&mut self) -> &mut S {
406 self.inner.as_mut().expect("inner only taken in drop")
407 }
408 }
409
410 impl<S, Req> Service<Req> for Cached<S>
411 where
412 S: Service<Req>,
413 {
414 type Response = S::Response;
415 type Error = S::Error;
416 type Future = S::Future;
417
418 fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
419 self.inner.as_mut().unwrap().poll_ready(cx).map_err(|err| {
420 self.is_closed = true;
421 err
422 })
423 }
424
425 fn call(&mut self, req: Req) -> Self::Future {
426 self.inner.as_mut().unwrap().call(req)
427 }
428 }
429
430 impl<S> Drop for Cached<S> {
431 fn drop(&mut self) {
432 if self.is_closed {
433 return;
434 }
435 if let Some(value) = self.inner.take() {
436 if let Some(shared) = self.shared.upgrade() {
437 if let Ok(mut shared) = shared.lock() {
438 shared.put(value);
439 }
440 }
441 }
442 }
443 }
444
445 impl<S: fmt::Debug> fmt::Debug for Cached<S> {
446 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
447 f.debug_tuple("Cached")
448 .field(self.inner.as_ref().unwrap())
449 .finish()
450 }
451 }
452
453 impl<V> Shared<V> {
456 fn put(&mut self, val: V) {
457 if let Some(mut waiter) = self.waiters.pop_front() {
458 self.reservations.push((waiter.id, val));
459 if let Some(waker) = waiter.waker.take() {
460 waker.wake();
461 }
462 return;
463 }
464
465 self.services.push(val);
466 }
467
468 fn take_available(&mut self) -> Option<V> {
469 if self.waiters.is_empty() {
470 self.services.pop()
471 } else {
472 None
473 }
474 }
475
476 fn push_waiter(&mut self) -> WaiterId {
477 let id = WaiterId(self.next_waiter);
478 self.next_waiter = self.next_waiter.wrapping_add(1);
479 self.waiters.push_back(Waiter { id, waker: None });
480 id
481 }
482
483 fn store_waker(&mut self, id: WaiterId, waker: &Waker) {
484 if let Some(waiter) = self.waiters.iter_mut().find(|waiter| waiter.id == id) {
485 if waiter
486 .waker
487 .as_ref()
488 .is_none_or(|current| !current.will_wake(waker))
489 {
490 waiter.waker = Some(waker.clone());
491 }
492 }
493 }
494
495 fn take_reserved(&mut self, id: WaiterId) -> Option<V> {
496 let index = self
497 .reservations
498 .iter()
499 .position(|(reserved_id, _)| *reserved_id == id)?;
500 Some(self.reservations.remove(index).1)
501 }
502
503 fn cancel_waiter(&mut self, id: WaiterId) {
504 if let Some(index) = self.waiters.iter().position(|waiter| waiter.id == id) {
505 self.waiters.remove(index);
506 return;
507 }
508
509 if let Some(svc) = self.take_reserved(id) {
510 self.put(svc);
511 }
512 }
513 }
514
515 pub struct BackgroundConnect<CF, S> {
516 future: CF,
517 shared: Weak<Mutex<Shared<S>>>,
518 }
519
520 impl<CF, S, E> Future for BackgroundConnect<CF, S>
521 where
522 CF: Future<Output = Result<S, E>> + Unpin,
523 {
524 type Output = ();
525
526 fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
527 match ready!(Pin::new(&mut self.future).poll(cx)) {
528 Ok(svc) => {
529 if let Some(shared) = self.shared.upgrade() {
530 if let Ok(mut locked) = shared.lock() {
531 locked.put(svc);
532 }
533 }
534 Poll::Ready(())
535 }
536 Err(_e) => Poll::Ready(()),
537 }
538 }
539 }
540}
541
542mod events {
543 #[derive(Clone, Debug)]
544 #[non_exhaustive]
545 pub struct Ignore;
546
547 #[derive(Clone, Debug)]
548 pub struct WithExecutor<E>(pub(super) E);
549
550 pub trait Events<CF> {
551 fn on_race_lost(&self, fut: CF);
552 }
553
554 impl<CF> Events<CF> for Ignore {
555 fn on_race_lost(&self, _fut: CF) {}
556 }
557
558 impl<E, CF> Events<CF> for WithExecutor<E>
559 where
560 E: hyper::rt::Executor<CF>,
561 {
562 fn on_race_lost(&self, fut: CF) {
563 self.0.execute(fut);
564 }
565 }
566}
567
568#[cfg(test)]
569mod tests {
570 use std::convert::Infallible;
571 use std::sync::{
572 Arc, Mutex,
573 atomic::{AtomicUsize, Ordering},
574 };
575 use std::task::{self, Poll};
576
577 use futures_util::future;
578 use tower_service::Service;
579 use tower_test::assert_request_eq;
580
581 #[tokio::test]
582 async fn test_makes_svc_when_empty() {
583 let (mock, mut handle) = tower_test::mock::pair();
584 let mut cache = super::builder().build(mock);
585 handle.allow(1);
586
587 std::future::poll_fn(|cx| cache.poll_ready(cx))
588 .await
589 .unwrap();
590
591 let f = cache.call(1);
592
593 future::join(f, async move {
594 assert_request_eq!(handle, 1).send_response("one");
595 })
596 .await
597 .0
598 .expect("call");
599 }
600
601 #[tokio::test]
602 async fn test_reuses_after_idle() {
603 let (mock, mut handle) = tower_test::mock::pair();
604 let mut cache = super::builder().build(mock);
605
606 handle.allow(1);
608
609 std::future::poll_fn(|cx| cache.poll_ready(cx))
610 .await
611 .unwrap();
612 let f = cache.call(1);
613 let cached = future::join(f, async {
614 assert_request_eq!(handle, 1).send_response("one");
615 })
616 .await
617 .0
618 .expect("call");
619 drop(cached);
620
621 std::future::poll_fn(|cx| cache.poll_ready(cx))
622 .await
623 .unwrap();
624 let f = cache.call(1);
625 let cached = f.await.expect("call");
626 drop(cached);
627 }
628
629 #[tokio::test]
632 async fn test_waiters_woken_in_fifo_order() {
633 use std::task::{Context, Poll, Waker};
634
635 let (mock, mut handle) = tower_test::mock::pair::<u32, &'static str>();
636 let mut cache = super::builder().build(mock);
637 handle.allow(16);
638
639 std::future::poll_fn(|cx| cache.poll_ready(cx))
642 .await
643 .unwrap();
644 let held = future::join(cache.call(0), async {
645 assert_request_eq!(handle, 0).send_response("conn");
646 })
647 .await
648 .0
649 .expect("call");
650
651 let mut cx = Context::from_waker(Waker::noop());
654 std::future::poll_fn(|cx| cache.poll_ready(cx))
655 .await
656 .unwrap();
657 let mut first = Box::pin(cache.call(1));
658 assert!(first.as_mut().poll(&mut cx).is_pending());
659 std::future::poll_fn(|cx| cache.poll_ready(cx))
660 .await
661 .unwrap();
662 let mut second = Box::pin(cache.call(2));
663 assert!(second.as_mut().poll(&mut cx).is_pending());
664 std::future::poll_fn(|cx| cache.poll_ready(cx))
665 .await
666 .unwrap();
667 let mut third = Box::pin(cache.call(3));
668 assert!(third.as_mut().poll(&mut cx).is_pending());
669
670 drop(held);
672 let first = match first.as_mut().poll(&mut cx) {
673 Poll::Ready(r) => r.expect("first"),
674 Poll::Pending => panic!("oldest waiter was not woken first"),
675 };
676 assert!(second.as_mut().poll(&mut cx).is_pending());
677 assert!(third.as_mut().poll(&mut cx).is_pending());
678
679 drop(first);
681 let second = match second.as_mut().poll(&mut cx) {
682 Poll::Ready(r) => r.expect("second"),
683 Poll::Pending => panic!("second waiter was not woken next"),
684 };
685 assert!(third.as_mut().poll(&mut cx).is_pending());
686
687 drop(second);
688 match third.as_mut().poll(&mut cx) {
689 Poll::Ready(r) => {
690 r.expect("third");
691 }
692 Poll::Pending => panic!("last waiter was not woken"),
693 }
694 }
695
696 #[tokio::test]
697 async fn dropped_racing_future_cancels_waiter() {
698 use std::task::{Context, Poll, Waker};
699
700 let (mock, mut handle) = tower_test::mock::pair::<u32, &'static str>();
701 let mut cache = super::builder().build(mock);
702 handle.allow(16);
703
704 std::future::poll_fn(|cx| cache.poll_ready(cx))
705 .await
706 .unwrap();
707 let held = future::join(cache.call(0), async {
708 assert_request_eq!(handle, 0).send_response("conn");
709 })
710 .await
711 .0
712 .expect("call");
713
714 std::future::poll_fn(|cx| cache.poll_ready(cx))
715 .await
716 .unwrap();
717 let mut dropped = Box::pin(cache.call(1));
718 let mut cx = Context::from_waker(Waker::noop());
719 assert!(dropped.as_mut().poll(&mut cx).is_pending());
720 drop(dropped);
721
722 drop(held);
723
724 std::future::poll_fn(|cx| cache.poll_ready(cx))
725 .await
726 .unwrap();
727 let mut reused = Box::pin(cache.call(2));
728 match reused.as_mut().poll(&mut cx) {
729 Poll::Ready(Ok(cached)) => {
730 assert_eq!(*cached.inner(), "conn");
731 }
732 Poll::Ready(Err(err)) => panic!("unexpected error: {err}"),
733 Poll::Pending => panic!("dropped waiter blocked idle reuse"),
734 }
735 }
736
737 #[tokio::test]
738 async fn clone_readiness_reserves_idle_service() {
739 let connector = StrictConnector::default();
740 let poll_ready_count = connector.poll_ready_count.clone();
741 let calls = connector.calls.clone();
742 let mut cache = super::builder().build(connector);
743
744 std::future::poll_fn(|cx| cache.poll_ready(cx))
745 .await
746 .unwrap();
747 let cached = cache.call(1).await.unwrap();
748 assert_eq!(*cached.inner(), 0);
749 drop(cached);
750
751 let mut a = cache.clone();
752 let mut b = cache.clone();
753
754 std::future::poll_fn(|cx| a.poll_ready(cx)).await.unwrap();
755 assert_eq!(poll_ready_count.load(Ordering::SeqCst), 1);
756 assert!(!a.is_empty());
757
758 std::future::poll_fn(|cx| b.poll_ready(cx)).await.unwrap();
759 assert_eq!(poll_ready_count.load(Ordering::SeqCst), 2);
760
761 let a_cached = a.call(10).await.unwrap();
762 assert_eq!(*a_cached.inner(), 0);
763
764 let b_cached = b.call(20).await.unwrap();
765 assert_eq!(*b_cached.inner(), 1);
766
767 assert_eq!(*calls.lock().unwrap(), vec![1, 20]);
768 }
769
770 #[tokio::test]
771 async fn dropped_ready_slot_returns_idle_service() {
772 let connector = StrictConnector::default();
773 let poll_ready_count = connector.poll_ready_count.clone();
774 let mut cache = super::builder().build(connector);
775
776 std::future::poll_fn(|cx| cache.poll_ready(cx))
777 .await
778 .unwrap();
779 let cached = cache.call(1).await.unwrap();
780 drop(cached);
781
782 let mut clone = cache.clone();
783 std::future::poll_fn(|cx| clone.poll_ready(cx))
784 .await
785 .unwrap();
786 drop(clone);
787
788 std::future::poll_fn(|cx| cache.poll_ready(cx))
789 .await
790 .unwrap();
791 assert_eq!(poll_ready_count.load(Ordering::SeqCst), 1);
792
793 let cached = cache.call(2).await.unwrap();
794 assert_eq!(*cached.inner(), 0);
795 }
796
797 #[tokio::test]
798 async fn retain_checks_ready_slot() {
799 let connector = StrictConnector::default();
800 let poll_ready_count = connector.poll_ready_count.clone();
801 let mut cache = super::builder().build(connector);
802
803 std::future::poll_fn(|cx| cache.poll_ready(cx))
804 .await
805 .unwrap();
806 let cached = cache.call(1).await.unwrap();
807 drop(cached);
808
809 std::future::poll_fn(|cx| cache.poll_ready(cx))
810 .await
811 .unwrap();
812 assert!(!cache.is_empty());
813
814 cache.retain(|svc| *svc != 0);
815 assert!(cache.is_empty());
816
817 std::future::poll_fn(|cx| cache.poll_ready(cx))
818 .await
819 .unwrap();
820 assert_eq!(poll_ready_count.load(Ordering::SeqCst), 2);
821 }
822
823 #[tokio::test]
824 async fn idle_return_wakes_pending_poll_ready() {
825 use std::sync::atomic::AtomicBool;
826 use std::task::{Context, Waker};
827
828 let connector = PendingConnector::default();
829 let allow_ready = connector.allow_ready.clone();
830 let mut cache = super::builder().build(connector);
831
832 allow_ready.store(true, Ordering::SeqCst);
833 std::future::poll_fn(|cx| cache.poll_ready(cx))
834 .await
835 .unwrap();
836 let held = cache.call(1).await.unwrap();
837 assert_eq!(*held.inner(), 0);
838
839 let mut ready = Box::pin(std::future::poll_fn(|cx| cache.poll_ready(cx)));
840 let mut cx = Context::from_waker(Waker::noop());
841 assert!(ready.as_mut().poll(&mut cx).is_pending());
842
843 drop(held);
844
845 match ready.as_mut().poll(&mut cx) {
846 Poll::Ready(Ok(())) => {}
847 Poll::Ready(Err(err)) => match err {},
848 Poll::Pending => panic!("idle return did not wake pending poll_ready"),
849 }
850 drop(ready);
851
852 let cached = cache.call(2).await.unwrap();
853 assert_eq!(*cached.inner(), 0);
854
855 #[derive(Default)]
856 struct PendingConnector {
857 allow_ready: Arc<AtomicBool>,
858 next: Arc<AtomicUsize>,
859 ready: bool,
860 }
861
862 impl Service<usize> for PendingConnector {
863 type Response = usize;
864 type Error = Infallible;
865 type Future = std::future::Ready<Result<usize, Infallible>>;
866
867 fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
868 if self.allow_ready.swap(false, Ordering::SeqCst) {
869 self.ready = true;
870 Poll::Ready(Ok(()))
871 } else {
872 Poll::Pending
873 }
874 }
875
876 fn call(&mut self, _target: usize) -> Self::Future {
877 assert!(self.ready, "connector called without poll_ready");
878 self.ready = false;
879 let id = self.next.fetch_add(1, Ordering::SeqCst);
880 std::future::ready(Ok(id))
881 }
882 }
883 }
884
885 #[derive(Default)]
886 struct StrictConnector {
887 poll_ready_count: Arc<AtomicUsize>,
888 next: Arc<AtomicUsize>,
889 calls: Arc<Mutex<Vec<usize>>>,
890 ready: bool,
891 }
892
893 impl Clone for StrictConnector {
894 fn clone(&self) -> Self {
895 StrictConnector {
896 poll_ready_count: self.poll_ready_count.clone(),
897 next: self.next.clone(),
898 calls: self.calls.clone(),
899 ready: false,
900 }
901 }
902 }
903
904 impl Service<usize> for StrictConnector {
905 type Response = usize;
906 type Error = Infallible;
907 type Future = std::future::Ready<Result<usize, Infallible>>;
908
909 fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
910 self.ready = true;
911 self.poll_ready_count.fetch_add(1, Ordering::SeqCst);
912 Poll::Ready(Ok(()))
913 }
914
915 fn call(&mut self, target: usize) -> Self::Future {
916 assert!(self.ready, "connector called without poll_ready");
917 self.ready = false;
918 self.calls.lock().unwrap().push(target);
919 let id = self.next.fetch_add(1, Ordering::SeqCst);
920 std::future::ready(Ok(id))
921 }
922 }
923}