Skip to content

Commit

Permalink
feat(#140, hash_index): implement any_entry and any_entry_async
Browse files Browse the repository at this point in the history
  • Loading branch information
wvwwvwwv committed Jun 29, 2024
1 parent 4c1d46c commit dee0de7
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 30 deletions.
60 changes: 32 additions & 28 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Version 2

2.2.0

* Implement `any_entry` and `any_entry_async` ([#148](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/148)).

2.1.1

* Implement `Deref` and `DerefMut` for `OccupiedEntry`: [#140](https://github.com/wvwwvwwv/scalable-concurrent-containers/issues/140) by [gituser-rs](https://github.com/gituser-rs)
Expand Down Expand Up @@ -97,31 +101,31 @@

### API update

- `*::Visitor` -> `*::Iter`.
- `*::Accessor` -> `*::IterMut`.
- `ebr::Arc` -> `ebr::Shared`.
- `ebr::Arc::get_ref_with` -> `ebr::Shared::get_guarded_ref`.
- `ebr::Arc::ptr` -> `ebr::Shared::get_guarded_ptr`.
- `ebr::Arc::release_drop_in_place` -> `ebr::Shared::drop_in_place`.
- `ebr::AtomicArc` -> `ebr::AtomicShared`.
- `ebr::AtomicArc::get_arc` -> `ebr::AtomicShared::get_shared`.
- `ebr::AtomicArc::try_into_arc` -> `ebr::AtomicShared::into_shared`.
- `ebr::AtomicOwned::try_into_owned` -> `ebr::AtomicOwned::into_owned`.
- `ebr::Barrier` -> `ebr::Guard`.
- `ebr::Owned::get_ref_with` -> `ebr::Owned::get_guarded_ref`.
- `ebr::Owned::ptr` -> `ebr::Owned::get_guarded_ptr`.
- `ebr::Ptr::as_raw` -> `ebr::Ptr::as_ptr`.
- `ebr::Ptr::get_arc` -> `ebr::Ptr::get_shared`.
- `*::first_occupied_entry*` -> `*::first_entry*`.
- `HashIndex::read` -> `HashIndex::peek_with`.
- `HashIndex::read_with` -> `HashIndex::peek`.
- `Queue::peek` -> `Queue::peek_with`.
- `Queue::peek_with` -> `Queue::peek`.
- `Stack::peek` -> `Stack::peek_with`.
- `Stack::peek_with` -> `Stack::peek`.
- `TreeIndex::read` -> `TreeIndex::peek_with`.
- `TreeIndex::read_with` -> `TreeIndex::peek`.
- Remove `HashMap::upsert*`: superseded by `hash_map::Entry::and_modify` and `hash_map::Entry::or_insert`.
* `*::Visitor` -> `*::Iter`.
* `*::Accessor` -> `*::IterMut`.
* `ebr::Arc` -> `ebr::Shared`.
* `ebr::Arc::get_ref_with` -> `ebr::Shared::get_guarded_ref`.
* `ebr::Arc::ptr` -> `ebr::Shared::get_guarded_ptr`.
* `ebr::Arc::release_drop_in_place` -> `ebr::Shared::drop_in_place`.
* `ebr::AtomicArc` -> `ebr::AtomicShared`.
* `ebr::AtomicArc::get_arc` -> `ebr::AtomicShared::get_shared`.
* `ebr::AtomicArc::try_into_arc` -> `ebr::AtomicShared::into_shared`.
* `ebr::AtomicOwned::try_into_owned` -> `ebr::AtomicOwned::into_owned`.
* `ebr::Barrier` -> `ebr::Guard`.
* `ebr::Owned::get_ref_with` -> `ebr::Owned::get_guarded_ref`.
* `ebr::Owned::ptr` -> `ebr::Owned::get_guarded_ptr`.
* `ebr::Ptr::as_raw` -> `ebr::Ptr::as_ptr`.
* `ebr::Ptr::get_arc` -> `ebr::Ptr::get_shared`.
* `*::first_occupied_entry*` -> `*::first_entry*`.
* `HashIndex::read` -> `HashIndex::peek_with`.
* `HashIndex::read_with` -> `HashIndex::peek`.
* `Queue::peek` -> `Queue::peek_with`.
* `Queue::peek_with` -> `Queue::peek`.
* `Stack::peek` -> `Stack::peek_with`.
* `Stack::peek_with` -> `Stack::peek`.
* `TreeIndex::read` -> `TreeIndex::peek_with`.
* `TreeIndex::read_with` -> `TreeIndex::peek`.
* Remove `HashMap::upsert*`: superseded by `hash_map::Entry::and_modify` and `hash_map::Entry::or_insert`.

```rust
use scc::HashMap;
Expand All @@ -132,7 +136,7 @@ let hashmap: HashMap<u64, u32> = HashMap::default();
hashmap.entry(1).and_modify(|v| { *v = 3 }).or_insert(2);
```

- Remove `HashIndex::modify*` and `HashIndex::update*`: superseded by `HashIndex::entry*`, `HashIndex::get*`.
* Remove `HashIndex::modify*` and `HashIndex::update*`: superseded by `HashIndex::entry*`, `HashIndex::get*`.

```rust
use scc::HashIndex;
Expand All @@ -151,7 +155,7 @@ if let Some(mut o) = hashindex.get(&1) {
};
```

- Remove `Hash*::for_each*`: superseded by `HashMap::retain*`.
* Remove `Hash*::for_each*`: superseded by `HashMap::retain*`.

```rust
use scc::HashMap;
Expand All @@ -163,7 +167,7 @@ assert!(hashmap.insert(1, 1).is_ok());
hashmap.retain(|_, v| { *v = 2; true });
```

- `Hash*::clear*`, `Hash*::prune*`, and `Hash*::retain*` return `()`.
* `Hash*::clear*`, `Hash*::prune*`, and `Hash*::retain*` return `()`.

## Version 1

Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "scc"
description = "High performance containers and utilities for concurrent and asynchronous programming"
documentation = "https://docs.rs/scc"
version = "2.1.1"
version = "2.2.0"
authors = ["wvwwvwwv <[email protected]>"]
edition = "2021"
rust-version = "1.65.0"
Expand All @@ -26,7 +26,7 @@ proptest = "1.4"
rand = "0.8"
serde_test = "1.0"
static_assertions = "1.1"
tokio = { version = "1.37", features = ["full"] }
tokio = { version = "1.38", features = ["full"] }

[[bench]]
name = "bag"
Expand Down
76 changes: 76 additions & 0 deletions src/hash_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,82 @@ where
None
}

/// Finds any entry satisfying the supplied predicate for in-place manipulation.
///
/// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
/// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
///
/// # Examples
///
/// ```
/// use scc::HashIndex;
///
/// let hashindex: HashIndex<u64, u32> = HashIndex::default();
///
/// assert!(hashindex.insert(1, 0).is_ok());
/// assert!(hashindex.insert(2, 3).is_ok());
///
/// let mut entry = hashindex.any_entry(|k, _| *k == 2).unwrap();
/// assert_eq!(*entry.get(), 3);
/// ```
#[inline]
pub fn any_entry<P: FnMut(&K, &V) -> bool>(
&self,
mut pred: P,
) -> Option<OccupiedEntry<K, V, H>> {
let guard = Guard::new();
let prolonged_guard = self.prolonged_guard_ref(&guard);
if let Some(locked_entry) = self.lock_first_entry(prolonged_guard) {
let mut entry = OccupiedEntry {
hashindex: self,
locked_entry,
};
loop {
if pred(entry.key(), entry.get()) {
return Some(entry);
}
entry = entry.next()?;
}
}
None
}

/// Finds any entry satisfying the supplied predicate for in-place manipulation.
///
/// The returned [`OccupiedEntry`] in combination with [`OccupiedEntry::next`] or
/// [`OccupiedEntry::next_async`] can act as a mutable iterator over entries.
///
/// It is an asynchronous method returning an `impl Future` for the caller to await.
///
/// # Examples
///
/// ```
/// use scc::HashIndex;
///
/// let hashindex: HashIndex<char, u32> = HashIndex::default();
///
/// let future_entry = hashindex.any_entry_async(|k, _| *k == 'a');
/// ```
#[inline]
pub async fn any_entry_async<P: FnMut(&K, &V) -> bool>(
&self,
mut pred: P,
) -> Option<OccupiedEntry<K, V, H>> {
if let Some(locked_entry) = LockedEntry::first_entry_async(self).await {
let mut entry = OccupiedEntry {
hashindex: self,
locked_entry,
};
loop {
if pred(entry.key(), entry.get()) {
return Some(entry);
}
entry = entry.next_async().await?;
}
}
None
}

/// Inserts a key-value pair into the [`HashIndex`].
///
/// # Errors
Expand Down

0 comments on commit dee0de7

Please sign in to comment.