Revert "refactor(lib): convert to futures 0.2.0-beta (#1470)"

This reverts commit a12f7beed9.

Much sadness 😢.
This commit is contained in:
Sean McArthur
2018-04-07 10:19:50 -07:00
parent 72e02d6ac8
commit 625e4daaa1
34 changed files with 1368 additions and 1386 deletions

View File

@@ -4,13 +4,15 @@ use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, Weak};
use std::time::{Duration, Instant};
use futures::{Future, Async, Never, Poll, Stream};
use futures::channel::oneshot;
use futures::task;
use futures::{Future, Async, Poll, Stream};
use futures::sync::oneshot;
use futures_timer::Interval;
pub(super) struct Pool<T> {
inner: Arc<Mutex<PoolInner<T>>>
use common::Never;
use super::Exec;
pub struct Pool<T> {
inner: Arc<Mutex<PoolInner<T>>>,
}
// Before using a pooled connection, make sure the sender is not dead.
@@ -44,7 +46,7 @@ struct PoolInner<T> {
}
impl<T> Pool<T> {
pub(super) fn new(enabled: bool, timeout: Option<Duration>) -> Pool<T> {
pub fn new(enabled: bool, timeout: Option<Duration>) -> Pool<T> {
Pool {
inner: Arc::new(Mutex::new(PoolInner {
enabled: enabled,
@@ -52,7 +54,7 @@ impl<T> Pool<T> {
idle_interval_ref: None,
parked: HashMap::new(),
timeout: timeout,
}))
})),
}
}
}
@@ -63,7 +65,6 @@ impl<T: Closed> Pool<T> {
key: Arc::new(key.to_owned()),
pool: self.clone(),
parked: None,
spawned_expired_interval: false
}
}
@@ -218,16 +219,16 @@ impl<T: Closed> PoolInner<T> {
impl<T: Closed + Send + 'static> Pool<T> {
fn spawn_expired_interval(&mut self, cx: &mut task::Context) -> Result<(), ::Error> {
pub(super) fn spawn_expired_interval(&self, exec: &Exec) {
let (dur, rx) = {
let mut inner = self.inner.lock().unwrap();
if !inner.enabled {
return Ok(());
return;
}
if inner.idle_interval_ref.is_some() {
return Ok(());
return;
}
if let Some(dur) = inner.timeout {
@@ -235,23 +236,23 @@ impl<T: Closed + Send + 'static> Pool<T> {
inner.idle_interval_ref = Some(tx);
(dur, rx)
} else {
return Ok(());
return
}
};
let interval = Interval::new(dur);
super::execute(IdleInterval {
exec.execute(IdleInterval {
interval: interval,
pool: Arc::downgrade(&self.inner),
pool_drop_notifier: rx,
}, cx)
}).unwrap();
}
}
impl<T> Clone for Pool<T> {
fn clone(&self) -> Pool<T> {
Pool {
inner: self.inner.clone()
inner: self.inner.clone(),
}
}
}
@@ -321,23 +322,22 @@ pub struct Checkout<T> {
key: Arc<String>,
pool: Pool<T>,
parked: Option<oneshot::Receiver<T>>,
spawned_expired_interval: bool
}
struct NotParked;
impl<T: Closed> Checkout<T> {
fn poll_parked(&mut self, cx: &mut task::Context) -> Poll<Pooled<T>, NotParked> {
fn poll_parked(&mut self) -> Poll<Pooled<T>, NotParked> {
let mut drop_parked = false;
if let Some(ref mut rx) = self.parked {
match rx.poll(cx) {
match rx.poll() {
Ok(Async::Ready(value)) => {
if !value.is_closed() {
return Ok(Async::Ready(self.pool.reuse(&self.key, value)));
}
drop_parked = true;
},
Ok(Async::Pending) => return Ok(Async::Pending),
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(_canceled) => drop_parked = true,
}
}
@@ -347,27 +347,22 @@ impl<T: Closed> Checkout<T> {
Err(NotParked)
}
fn park(&mut self, cx: &mut task::Context) {
fn park(&mut self) {
if self.parked.is_none() {
let (tx, mut rx) = oneshot::channel();
let _ = rx.poll(cx); // park this task
let _ = rx.poll(); // park this task
self.pool.park(self.key.clone(), tx);
self.parked = Some(rx);
}
}
}
impl<T: Closed + Send + 'static> Future for Checkout<T> {
impl<T: Closed> Future for Checkout<T> {
type Item = Pooled<T>;
type Error = ::Error;
fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
if !self.spawned_expired_interval {
self.pool.spawn_expired_interval(cx)?;
self.spawned_expired_interval = true;
}
match self.poll_parked(cx) {
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.poll_parked() {
Ok(async) => return Ok(async),
Err(_not_parked) => (),
}
@@ -377,8 +372,8 @@ impl<T: Closed + Send + 'static> Future for Checkout<T> {
if let Some(pooled) = entry {
Ok(Async::Ready(pooled))
} else {
self.park(cx);
Ok(Async::Pending)
self.park();
Ok(Async::NotReady)
}
}
}
@@ -418,20 +413,20 @@ struct IdleInterval<T> {
impl<T: Closed + 'static> Future for IdleInterval<T> {
type Item = ();
type Error = Never;
type Error = ();
fn poll(&mut self, cx: &mut task::Context) -> Poll<Self::Item, Self::Error> {
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
match self.pool_drop_notifier.poll(cx) {
match self.pool_drop_notifier.poll() {
Ok(Async::Ready(n)) => match n {},
Ok(Async::Pending) => (),
Ok(Async::NotReady) => (),
Err(_canceled) => {
trace!("pool closed, canceling idle interval");
return Ok(Async::Ready(()));
}
}
try_ready!(self.interval.poll_next(cx).map_err(|_| unreachable!("interval cannot error")));
try_ready!(self.interval.poll().map_err(|_| unreachable!("interval cannot error")));
if let Some(inner) = self.pool.upgrade() {
if let Ok(mut inner) = inner.lock() {
@@ -448,10 +443,9 @@ impl<T: Closed + 'static> Future for IdleInterval<T> {
mod tests {
use std::sync::Arc;
use std::time::Duration;
use futures::{Async, Future, FutureExt};
use futures::{Async, Future};
use futures::future;
use futures::executor::block_on;
use super::{Closed, Pool};
use super::{Closed, Pool, Exec};
impl Closed for i32 {
fn is_closed(&self) -> bool {
@@ -461,37 +455,34 @@ mod tests {
#[test]
fn test_pool_checkout_smoke() {
block_on(future::lazy(|cx| {
let pool = Pool::new(true, Some(Duration::from_secs(5)));
let key = Arc::new("foo".to_string());
let pooled = pool.pooled(key.clone(), 41);
let pool = Pool::new(true, Some(Duration::from_secs(5)));
let key = Arc::new("foo".to_string());
let pooled = pool.pooled(key.clone(), 41);
drop(pooled);
drop(pooled);
match pool.checkout(&key).poll(cx).unwrap() {
Async::Ready(pooled) => assert_eq!(*pooled, 41),
_ => panic!("not ready"),
}
Ok::<_, ()>(())
})).unwrap();
match pool.checkout(&key).poll().unwrap() {
Async::Ready(pooled) => assert_eq!(*pooled, 41),
_ => panic!("not ready"),
}
}
#[test]
fn test_pool_checkout_returns_none_if_expired() {
block_on(future::lazy(|cx| {
future::lazy(|| {
let pool = Pool::new(true, Some(Duration::from_millis(100)));
let key = Arc::new("foo".to_string());
let pooled = pool.pooled(key.clone(), 41);
drop(pooled);
::std::thread::sleep(pool.inner.lock().unwrap().timeout.unwrap());
assert!(pool.checkout(&key).poll(cx).unwrap().is_pending());
Ok::<_, ()>(())
})).unwrap();
assert!(pool.checkout(&key).poll().unwrap().is_not_ready());
::futures::future::ok::<(), ()>(())
}).wait().unwrap();
}
#[test]
fn test_pool_checkout_removes_expired() {
block_on(future::lazy(|cx| {
future::lazy(|| {
let pool = Pool::new(true, Some(Duration::from_millis(100)));
let key = Arc::new("foo".to_string());
@@ -503,20 +494,20 @@ mod tests {
::std::thread::sleep(pool.inner.lock().unwrap().timeout.unwrap());
// checkout.poll() should clean out the expired
pool.checkout(&key).poll(cx).unwrap();
pool.checkout(&key).poll().unwrap();
assert!(pool.inner.lock().unwrap().idle.get(&key).is_none());
Ok::<_, ()>(())
})).unwrap();
Ok::<(), ()>(())
}).wait().unwrap();
}
#[test]
fn test_pool_timer_removes_expired() {
let mut pool = Pool::new(true, Some(Duration::from_millis(100)));
let runtime = ::tokio::runtime::Runtime::new().unwrap();
let pool = Pool::new(true, Some(Duration::from_millis(100)));
block_on(future::lazy(|cx| {
pool.spawn_expired_interval(cx)
})).unwrap();
let executor = runtime.executor();
pool.spawn_expired_interval(&Exec::new(executor));
let key = Arc::new("foo".to_string());
pool.pooled(key.clone(), 41);
@@ -525,9 +516,9 @@ mod tests {
assert_eq!(pool.inner.lock().unwrap().idle.get(&key).map(|entries| entries.len()), Some(3));
block_on(::futures_timer::Delay::new(
::futures_timer::Delay::new(
Duration::from_millis(400) // allow for too-good resolution
)).unwrap();
).wait().unwrap();
assert!(pool.inner.lock().unwrap().idle.get(&key).is_none());
}
@@ -538,7 +529,7 @@ mod tests {
let key = Arc::new("foo".to_string());
let pooled = pool.pooled(key.clone(), 41);
let checkout = pool.checkout(&key).join(future::lazy(move |_| {
let checkout = pool.checkout(&key).join(future::lazy(move || {
// the checkout future will park first,
// and then this lazy future will be polled, which will insert
// the pooled back into the pool
@@ -547,12 +538,12 @@ mod tests {
drop(pooled);
Ok(())
})).map(|(entry, _)| entry);
assert_eq!(*block_on(checkout).unwrap(), 41);
assert_eq!(*checkout.wait().unwrap(), 41);
}
#[test]
fn test_pool_checkout_drop_cleans_up_parked() {
block_on(future::lazy(|cx| {
future::lazy(|| {
let pool = Pool::<i32>::new(true, Some(Duration::from_secs(10)));
let key = Arc::new("localhost:12345".to_string());
@@ -560,9 +551,9 @@ mod tests {
let mut checkout2 = pool.checkout(&key);
// first poll needed to get into Pool's parked
checkout1.poll(cx).unwrap();
checkout1.poll().unwrap();
assert_eq!(pool.inner.lock().unwrap().parked.get(&key).unwrap().len(), 1);
checkout2.poll(cx).unwrap();
checkout2.poll().unwrap();
assert_eq!(pool.inner.lock().unwrap().parked.get(&key).unwrap().len(), 2);
// on drop, clean up Pool
@@ -572,7 +563,7 @@ mod tests {
drop(checkout2);
assert!(pool.inner.lock().unwrap().parked.get(&key).is_none());
Ok::<_, ()>(())
})).unwrap();
::futures::future::ok::<(), ()>(())
}).wait().unwrap();
}
}