pub struct RepVecRangeLock<T> { /* private fields */ }
Expand description
Interleaved multi-thread range lock for std::vec::Vec.
Each thread can lock a set of repeating slices of the data.
The slices are interleaved with each other
and the slice pattern cyclically repeats at cycle_len
rate.
Offsets are not bound to one specific thread.
Please see the example below.
§Example
use range_lock::RepVecRangeLock;
use std::{sync::Arc, thread};
let data = vec![1, 2, 3, 4, 5, 6, // <- cycle 0
7, 8, 9, 10, 11, 12]; // <- cycle 1
// ^--^ ^---^ ^----^
// | | |
// offset-0 offset-1 offset-2
let lock = Arc::new(RepVecRangeLock::new(data,
2, // slice_len: Each slice has 2 elements.
3)); // cycle_len: Each cycle has 3 slices (offsets).
let lock0 = Arc::clone(&lock);
let lock1 = Arc::clone(&lock);
let lock2 = Arc::clone(&lock);
thread::scope(|s| {
s.spawn(move || {
// Lock slice offset 0:
let mut guard = lock0.try_lock(0).expect("Failed to lock offset.");
// Read:
assert_eq!(guard[0][0], 1); // Cycle 0, Slice element 0
assert_eq!(guard[0][1], 2); // Cycle 0, Slice element 1
// let _ = guard[0][2]; // Would panic. Slice len is only 2.
assert_eq!(guard[1][0], 7); // Cycle 1, Slice element 0
assert_eq!(guard[1][1], 8); // Cycle 1, Slice element 1
// let _ = guard[2][0]; // Would panic: The data vec is only 2 repeat cycles long.
// Write:
guard[0][0] = 10; // Cycle 0, Slice element 0
guard[0][1] = 20; // Cycle 0, Slice element 1
// guard[0][2] = 42; // Would panic: Slice len is only 2.
guard[1][0] = 30; // Cycle 1, Slice element 0
guard[1][1] = 40; // Cycle 1, Slice element 1
// guard[2][0] = 42; // Would panic: The data vec is only 2 repeat cycles long.
});
s.spawn(move || {
// Lock slice offset 1:
let mut guard = lock1.try_lock(1).expect("Failed to lock offset.");
guard[0][0] = 100; // Cycle 0, Slice element 0
guard[0][1] = 200; // Cycle 0, Slice element 1
guard[1][0] = 300; // Cycle 1, Slice element 0
guard[1][1] = 400; // Cycle 1, Slice element 1
});
s.spawn(move || {
// Lock slice offset 2:
let mut guard = lock2.try_lock(2).expect("Failed to lock offset.");
guard[0][0] = 1000; // Cycle 0, Slice element 0
guard[0][1] = 2000; // Cycle 0, Slice element 1
guard[1][0] = 3000; // Cycle 1, Slice element 0
guard[1][1] = 4000; // Cycle 1, Slice element 1
});
});
// Get the data that has been modified by the threads.
let data = Arc::try_unwrap(lock).expect("Thread is still using data.").into_inner();
assert_eq!(data,
vec![10, 20, 100, 200, 1000, 2000,
30, 40, 300, 400, 3000, 4000]);
Implementations§
Source§impl<'a, T> RepVecRangeLock<T>
impl<'a, T> RepVecRangeLock<T>
Sourcepub fn new(
data: Vec<T>,
slice_len: usize,
cycle_len: usize,
) -> RepVecRangeLock<T>
pub fn new( data: Vec<T>, slice_len: usize, cycle_len: usize, ) -> RepVecRangeLock<T>
Construct a new RepVecRangeLock.
data
: The data Vec to protect.slice_len
: The length of the slices, in number of elements. Must be >0.cycle_len
: The length of the repeat cycle, in number of slices. Must be >0 and <=usize::MAX-31.
Sourcepub fn into_inner(self) -> Vec<T>
pub fn into_inner(self) -> Vec<T>
Unwrap this RepVecRangeLock into the contained data. This method consumes self.
Sourcepub fn try_lock(
&'a self,
cycle_offset: usize,
) -> TryLockResult<RepVecRangeLockGuard<'a, T>>
pub fn try_lock( &'a self, cycle_offset: usize, ) -> TryLockResult<RepVecRangeLockGuard<'a, T>>
Try to lock the given data slice at ‘cycle_offset’.
- On success: Returns a RepVecRangeLockGuard that can be used to access the locked region.
Indexing RepVecRangeLockGuard yields a slice of the
data
. - On failure: Returns TryLockError::WouldBlock, if the slice is contended. The locking attempt may be retried by the caller upon contention. Returns TryLockError::Poisoned, if the lock is poisoned.
Trait Implementations§
Source§impl<T: Debug> Debug for RepVecRangeLock<T>
impl<T: Debug> Debug for RepVecRangeLock<T>
impl<T> Sync for RepVecRangeLock<T>where
T: Send,
Auto Trait Implementations§
impl<T> !Freeze for RepVecRangeLock<T>
impl<T> !RefUnwindSafe for RepVecRangeLock<T>
impl<T> Send for RepVecRangeLock<T>where
T: Send,
impl<T> Unpin for RepVecRangeLock<T>
impl<T> UnwindSafe for RepVecRangeLock<T>where
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more