refactor(client): change last Weak::new to an Option<Weak>
This commit is contained in:
		| @@ -50,11 +50,6 @@ type Key = (Arc<String>, Ver); | ||||
| struct PoolInner<T> { | ||||
|     connections: Mutex<Connections<T>>, | ||||
|     enabled: bool, | ||||
|     /// A single Weak pointer used every time a proper weak reference | ||||
|     /// is not needed. This prevents allocating space in the heap to hold | ||||
|     /// a PoolInner<T> *every single time*, and instead we just allocate | ||||
|     /// this one extra per pool. | ||||
|     weak: Weak<PoolInner<T>>, | ||||
| } | ||||
|  | ||||
| struct Connections<T> { | ||||
| @@ -84,6 +79,10 @@ struct Connections<T> { | ||||
|     timeout: Option<Duration>, | ||||
| } | ||||
|  | ||||
| // This is because `Weak::new()` *allocates* space for `T`, even if it | ||||
| // doesn't need it! | ||||
| struct WeakOpt<T>(Option<Weak<T>>); | ||||
|  | ||||
| impl<T> Pool<T> { | ||||
|     pub fn new(enabled: bool, timeout: Option<Duration>, __exec: &Exec) -> Pool<T> { | ||||
|         Pool { | ||||
| @@ -99,7 +98,6 @@ impl<T> Pool<T> { | ||||
|                     timeout, | ||||
|                 }), | ||||
|                 enabled, | ||||
|                 weak: Weak::new(), | ||||
|             }), | ||||
|         } | ||||
|     } | ||||
| @@ -136,7 +134,7 @@ impl<T: Poolable> Pool<T> { | ||||
|             if inner.connecting.insert(key.clone()) { | ||||
|                 let connecting = Connecting { | ||||
|                     key: key.clone(), | ||||
|                     pool: Arc::downgrade(&self.inner), | ||||
|                     pool: WeakOpt::downgrade(&self.inner), | ||||
|                 }; | ||||
|                 Some(connecting) | ||||
|             } else { | ||||
| @@ -148,7 +146,7 @@ impl<T: Poolable> Pool<T> { | ||||
|                 key: key.clone(), | ||||
|                 // in HTTP/1's case, there is never a lock, so we don't | ||||
|                 // need to do anything in Drop. | ||||
|                 pool: self.inner.weak.clone(), | ||||
|                 pool: WeakOpt::none(), | ||||
|             }) | ||||
|         } | ||||
|     } | ||||
| @@ -189,7 +187,7 @@ impl<T: Poolable> Pool<T> { | ||||
|     } | ||||
|  | ||||
|     pub(super) fn pooled(&self, mut connecting: Connecting<T>, value: T) -> Pooled<T> { | ||||
|         let (value, pool_ref, has_pool) = if self.inner.enabled { | ||||
|         let (value, pool_ref)  = if self.inner.enabled { | ||||
|             match value.reserve() { | ||||
|                 Reservation::Shared(to_insert, to_return) => { | ||||
|                     debug_assert_eq!( | ||||
| @@ -203,17 +201,17 @@ impl<T: Poolable> Pool<T> { | ||||
|                     // already have a lock, no need to lock the mutex twice. | ||||
|                     inner.connected(&connecting.key); | ||||
|                     // prevent the Drop of Connecting from repeating inner.connected() | ||||
|                     connecting.pool = self.inner.weak.clone(); | ||||
|                     connecting.pool = WeakOpt::none(); | ||||
|  | ||||
|                     // Shared reservations don't need a reference to the pool, | ||||
|                     // since the pool always keeps a copy. | ||||
|                     (to_return, self.inner.weak.clone(), false) | ||||
|                     (to_return, WeakOpt::none()) | ||||
|                 }, | ||||
|                 Reservation::Unique(value) => { | ||||
|                     // Unique reservations must take a reference to the pool | ||||
|                     // since they hope to reinsert once the reservation is | ||||
|                     // completed | ||||
|                     (value, Arc::downgrade(&self.inner), true) | ||||
|                     (value, WeakOpt::downgrade(&self.inner)) | ||||
|                 }, | ||||
|             } | ||||
|         } else { | ||||
| @@ -222,11 +220,10 @@ impl<T: Poolable> Pool<T> { | ||||
|             // The Connecting should have had no pool ref | ||||
|             debug_assert!(connecting.pool.upgrade().is_none()); | ||||
|  | ||||
|             (value, self.inner.weak.clone(), false) | ||||
|             (value, WeakOpt::none()) | ||||
|         }; | ||||
|         Pooled { | ||||
|             key: connecting.key.clone(), | ||||
|             has_pool, | ||||
|             is_reused: false, | ||||
|             pool: pool_ref, | ||||
|             value: Some(value) | ||||
| @@ -243,14 +240,13 @@ impl<T: Poolable> Pool<T> { | ||||
|         // we just have the final value, without knowledge of if this is | ||||
|         // unique or shared. So, the hack is to just assume Ver::Http2 means | ||||
|         // shared... :( | ||||
|         let (pool_ref, has_pool) = if key.1 == Ver::Http2 { | ||||
|             (self.inner.weak.clone(), false) | ||||
|         let pool_ref = if key.1 == Ver::Http2 { | ||||
|             WeakOpt::none() | ||||
|         } else { | ||||
|             (Arc::downgrade(&self.inner), true) | ||||
|             WeakOpt::downgrade(&self.inner) | ||||
|         }; | ||||
|  | ||||
|         Pooled { | ||||
|             has_pool, | ||||
|             is_reused: true, | ||||
|             key: key.clone(), | ||||
|             pool: pool_ref, | ||||
| @@ -414,7 +410,7 @@ impl<T: Poolable> Connections<T> { | ||||
|         let interval = Interval::new(start, dur); | ||||
|         self.exec.execute(IdleInterval { | ||||
|             interval: interval, | ||||
|             pool: Arc::downgrade(pool_ref), | ||||
|             pool: WeakOpt::downgrade(pool_ref), | ||||
|             pool_drop_notifier: rx, | ||||
|         }); | ||||
|     } | ||||
| @@ -481,10 +477,9 @@ impl<T> Clone for Pool<T> { | ||||
| // Note: The bounds `T: Poolable` is needed for the Drop impl. | ||||
| pub(super) struct Pooled<T: Poolable> { | ||||
|     value: Option<T>, | ||||
|     has_pool: bool, | ||||
|     is_reused: bool, | ||||
|     key: Key, | ||||
|     pool: Weak<PoolInner<T>>, | ||||
|     pool: WeakOpt<PoolInner<T>>, | ||||
| } | ||||
|  | ||||
| impl<T: Poolable> Pooled<T> { | ||||
| @@ -493,7 +488,7 @@ impl<T: Poolable> Pooled<T> { | ||||
|     } | ||||
|  | ||||
|     pub fn is_pool_enabled(&self) -> bool { | ||||
|         self.has_pool | ||||
|         self.pool.0.is_some() | ||||
|     } | ||||
|  | ||||
|     fn as_ref(&self) -> &T { | ||||
| @@ -628,7 +623,7 @@ impl<T> Drop for Checkout<T> { | ||||
|  | ||||
| pub(super) struct Connecting<T: Poolable> { | ||||
|     key: Key, | ||||
|     pool: Weak<PoolInner<T>>, | ||||
|     pool: WeakOpt<PoolInner<T>>, | ||||
| } | ||||
|  | ||||
| impl<T: Poolable> Drop for Connecting<T> { | ||||
| @@ -665,7 +660,7 @@ impl Expiration { | ||||
| #[cfg(feature = "runtime")] | ||||
| struct IdleInterval<T> { | ||||
|     interval: Interval, | ||||
|     pool: Weak<PoolInner<T>>, | ||||
|     pool: WeakOpt<PoolInner<T>>, | ||||
|     // This allows the IdleInterval to be notified as soon as the entire | ||||
|     // Pool is fully dropped, and shutdown. This channel is never sent on, | ||||
|     // but Err(Canceled) will be received when the Pool is dropped. | ||||
| @@ -707,14 +702,30 @@ impl<T: Poolable + 'static> Future for IdleInterval<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> WeakOpt<T> { | ||||
|     fn none() -> Self { | ||||
|         WeakOpt(None) | ||||
|     } | ||||
|  | ||||
|     fn downgrade(arc: &Arc<T>) -> Self { | ||||
|         WeakOpt(Some(Arc::downgrade(arc))) | ||||
|     } | ||||
|  | ||||
|     fn upgrade(&self) -> Option<Arc<T>> { | ||||
|         self.0 | ||||
|             .as_ref() | ||||
|             .and_then(Weak::upgrade) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use std::sync::{Arc, Weak}; | ||||
|     use std::sync::Arc; | ||||
|     use std::time::Duration; | ||||
|     use futures::{Async, Future}; | ||||
|     use futures::future; | ||||
|     use common::Exec; | ||||
|     use super::{Connecting, Key, Poolable, Pool, Reservation, Ver}; | ||||
|     use super::{Connecting, Key, Poolable, Pool, Reservation, Ver, WeakOpt}; | ||||
|  | ||||
|     /// Test unique reservations. | ||||
|     #[derive(Debug, PartialEq, Eq)] | ||||
| @@ -733,7 +744,7 @@ mod tests { | ||||
|     fn c<T: Poolable>(key: Key) -> Connecting<T> { | ||||
|         Connecting { | ||||
|             key, | ||||
|             pool: Weak::new(), | ||||
|             pool: WeakOpt::none(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user