Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,13 +462,26 @@ impl<
/// Inserts an item in the cache with key `key`.
pub fn insert_with_lifecycle(&self, key: Key, value: Val) -> L::RequestState {
let mut lcs = self.lifecycle.begin_request();
self.insert_with_state(key, value, &mut lcs);
lcs
}

/// Inserts an item in the cache with key `key` using an existing lifecycle request state.
///
/// `lcs` must have been obtained from a prior [`Lifecycle::begin_request`] call and
/// must **not** have been passed to [`Lifecycle::end_request`] yet. Any items evicted
/// by this insert are recorded into `lcs` and will be dropped when `end_request` is
/// eventually called.
///
/// Prefer [`insert`](Self::insert) for the common case where you do not need to
/// manage the lifecycle state manually.
pub fn insert_with_state(&self, key: Key, value: Val, lcs: &mut L::RequestState) {
let (shard, hash) = self.shard_for(&key).unwrap();
let result = shard
.write()
.insert(&mut lcs, hash, key, value, InsertStrategy::Insert);
.insert(lcs, hash, key, value, InsertStrategy::Insert);
// result cannot err with the Insert strategy
debug_assert!(result.is_ok());
lcs
}

/// Attempts to insert an item in the cache with key `key` without blocking.
Expand All @@ -484,14 +497,29 @@ impl<
// Tradeoff: begin_request is called before acquiring the shard lock to avoid holding
// the lock during potentially expensive lifecycle initialization.
let mut lcs = self.lifecycle.begin_request();
self.try_insert_with_state(key, value, &mut lcs)?;
Ok(lcs)
}

/// Attempts to insert an item in the cache with key `key` without blocking.
/// Returns `Ok(lcs)` with the lifecycle request state if the item was inserted,
/// or `Err((key, value))` if the shard lock could not be acquired without blocking.
/// Lock contention is the only failure mode: the inputs are returned so the
/// caller can retry or discard them.
pub fn try_insert_with_state(
&self,
key: Key,
value: Val,
lcs: &mut L::RequestState,
) -> Result<(), (Key, Val)> {
let (shard, hash) = self.shard_for(&key).unwrap();

match shard.try_write() {
Some(mut shard) => {
let result = shard.insert(&mut lcs, hash, key, value, InsertStrategy::Insert);
let result = shard.insert(lcs, hash, key, value, InsertStrategy::Insert);
// result cannot err with the Insert strategy
debug_assert!(result.is_ok());
Ok(lcs)
Ok(())
}
_ => Err((key, value)),
}
Expand Down
Loading