diff --git a/src/sync.rs b/src/sync.rs index 8810ec2..fb32a2f 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -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. @@ -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)), }