Skip to content

Commit

Permalink
Add RetainResult as return value of Pool::retain method
Browse files Browse the repository at this point in the history
This is related to #370
  • Loading branch information
bikeshedder committed Dec 19, 2024
1 parent 5890f7c commit 7b2f616
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Update `itertools` dependency to version `0.13.0`
- Change predicate parameter of `Pool::retain` method to `FnMut`
- Add `RetainResult` as return value of `Pool::retain` method

## [0.12.1] - 2024-05-07

Expand Down
46 changes: 38 additions & 8 deletions src/managed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,18 +519,30 @@ impl<M: Manager, W: From<Object<M>>> Pool<M, W> {
/// }
/// });
/// ```
pub fn retain(&self, mut f: impl FnMut(&M::Type, Metrics) -> bool) {
pub fn retain(
&self,
mut predicate: impl FnMut(&M::Type, Metrics) -> bool,
) -> RetainResult<M::Type> {
let mut removed = Vec::with_capacity(self.status().size);
let mut guard = self.inner.slots.lock().unwrap();
let len_before = guard.vec.len();
guard.vec.retain_mut(|obj| {
if f(&obj.obj, obj.metrics) {
true
let mut i = 0;
// This code can be simplified once `Vec::extract_if` lands in stable Rust.
// https://doc.rust-lang.org/std/vec/struct.Vec.html#method.extract_if
while i < guard.vec.len() {
let obj = &mut guard.vec[i];
if predicate(&mut obj.obj, obj.metrics) {
i += 1;
} else {
let mut obj = guard.vec.remove(i).unwrap();
self.manager().detach(&mut obj.obj);
false
removed.push(obj.obj);
}
});
guard.size -= len_before - guard.vec.len();
}
guard.size -= removed.len();
RetainResult {
retained: i,
removed,
}
}

/// Get current timeout configuration
Expand Down Expand Up @@ -661,3 +673,21 @@ async fn apply_timeout<O, E>(
(None, Some(_)) => Err(PoolError::NoRuntimeSpecified),
}
}

#[derive(Debug)]
/// This is the result returned by `Pool::retain`
pub struct RetainResult<T> {
/// Number of retained objects
pub retained: usize,
/// Objects that were removed from the pool
pub removed: Vec<T>,
}

impl<T> Default for RetainResult<T> {
fn default() -> Self {
Self {
retained: Default::default(),
removed: Default::default(),
}
}
}
13 changes: 10 additions & 3 deletions tests/managed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,14 @@ async fn retain() {
tokio::time::sleep(Duration::from_millis(5)).await;
}
assert_eq!(pool.status().size, 3);
pool.retain(|_, metrics| metrics.age() <= Duration::from_millis(10));
let retain_result = pool.retain(|_, metrics| metrics.age() <= Duration::from_millis(10));
assert_eq!(retain_result.retained, 1);
assert_eq!(retain_result.removed.len(), 2);
assert_eq!(pool.status().size, 1);
tokio::time::sleep(Duration::from_millis(5)).await;
pool.retain(|_, metrics| metrics.age() <= Duration::from_millis(10));
let retain_result = pool.retain(|_, metrics| metrics.age() <= Duration::from_millis(10));
assert_eq!(retain_result.retained, 0);
assert_eq!(retain_result.removed.len(), 1);
assert_eq!(pool.status().size, 0);
}

Expand All @@ -310,9 +314,12 @@ async fn retain_fnmut() {
}
let mut removed = 0;
{
pool.retain(|_, _| {
let retain_result = pool.retain(|_, _| {
removed += 1;
false
});
assert_eq!(retain_result.retained, 0);
assert_eq!(retain_result.removed.len(), 4);
}
assert_eq!(pool.status().size, 0);
}

0 comments on commit 7b2f616

Please sign in to comment.