pub struct ChainLockGuard<'a, T: Transaction> { /* private fields */ }Expand description
RAII-style acquire/release guard for ChainLock.
Implementations§
Source§impl<'a, T: Transaction> ChainLockGuard<'a, T>
impl<'a, T: Transaction> ChainLockGuard<'a, T>
Sourcepub fn new(
lock: &'a ChainLock<T>,
token: &'a ChainLockTransactionToken<T>,
) -> Self
pub fn new( lock: &'a ChainLock<T>, token: &'a ChainLockTransactionToken<T>, ) -> Self
Unconditionally acquires the given chain lock as the first lock in the chain.
Sourcepub const fn adopt(
lock: &'a ChainLock<T>,
_token: &'a ChainLockTransactionToken<T>,
) -> Self
pub const fn adopt( lock: &'a ChainLock<T>, _token: &'a ChainLockTransactionToken<T>, ) -> Self
Adopts the given chain lock that is already acquired via some other mechanism.
Sourcepub const fn defer(
lock: &'a ChainLock<T>,
_token: &'a ChainLockTransactionToken<T>,
) -> Self
pub const fn defer( lock: &'a ChainLock<T>, _token: &'a ChainLockTransactionToken<T>, ) -> Self
Associates the given lock capability with this scoped guard, but does not acquire it. This is useful in conjunction with the conditional acquire methods below.
§Example
let mut guard = ChainLockGuard::defer(&lock, token);
if guard.acquire_or_backoff() {
// Lock is acquired and guarded. It will be released when guard goes out of scope.
} else {
// Lock is not acquired or guarded. It will not be released when guard goes out of
// scope.
}Sourcepub fn from_taken(other: Self, lock: &'a ChainLock<T>) -> Self
pub fn from_taken(other: Self, lock: &'a ChainLock<T>) -> Self
Takes responsibility for lock from other. This is useful for moving the scope of a
lock acquisition deeper into the call stack in certain locking patterns.
Asserts in debug builds that other actually holds lock.
Sourcepub fn take(self) -> Self
pub fn take(self) -> Self
Releases the capability guarded by this instance without actually releasing the lock,
returning a moved guard intended to be passed to Self::from_taken or a callee.
Asserts in debug builds that this guard currently holds the lock.
Sourcepub fn acquire_or_backoff(&mut self) -> bool
pub fn acquire_or_backoff(&mut self) -> bool
Conditionally acquires the lock or returns false because of backoff.
Asserts in debug builds that the lock is not already held by this guard.
Sourcepub fn try_acquire(&mut self) -> bool
pub fn try_acquire(&mut self) -> bool
Conditionally acquires the lock with default options (AllowFinalized::No,
RecordBackoff::Yes) or returns false if failed.
Asserts in debug builds that the lock is not already held by this guard.
Sourcepub fn try_acquire_with_options(
&mut self,
allow_finalized: AllowFinalized,
record_backoff: RecordBackoff,
) -> bool
pub fn try_acquire_with_options( &mut self, allow_finalized: AllowFinalized, record_backoff: RecordBackoff, ) -> bool
Conditionally acquires the lock with the specified options or returns false if failed.
Asserts in debug builds that the lock is not already held by this guard.
Sourcepub fn try_acquire_with<F>(&mut self, callable: F) -> boolwhere
F: FnOnce(&'a ChainLock<T>) -> bool,
pub fn try_acquire_with<F>(&mut self, callable: F) -> boolwhere
F: FnOnce(&'a ChainLock<T>) -> bool,
Conditionally acquires the lock using the given callable, or returns false if failed.
This is useful in certain locking patterns where an additional predicate needs to be
injected into the lock condition.
Asserts in debug builds that the lock is not already held by this guard.
Sourcepub fn release(&mut self)
pub fn release(&mut self)
Releases the guarded lock and its capability.
Asserts in debug builds that the lock is currently held by this guard.
Sourcepub fn unguard(&mut self)
pub fn unguard(&mut self)
Prevents this guard from releasing the lock when it goes out of scope, but does not release the lock or its capability. This is a temporary workaround to allow guards to be used in scopes that will release the guarded lock in a function or method called in the guarded scope.
§Example
{
let mut guard = ChainLockGuard::new(object.get_lock(), token);
// Validation with lock held ...
guard.unguard(); // Avoid double release when guard destructs.
do_operation_and_release_lock(object, token);
}Possible alternatives to explore that could replace this workaround:
- Move the guard into the callee that will release the lock:
do_operation_and_release_lock(object, guard.take());- Make the guard destructor check that the lock is actually held to avoid the double release:
impl<T: Transaction> Drop for ChainLockGuard<'_, T> {
fn drop(&mut self) {
if self.held && self.lock.is_held(&self.token) {
self.lock.release(&self.token);
}
}
}All of these approaches have potential advantages and disadvantages that need to be considered.
Asserts in debug builds that the lock is currently held by this guard.