Struct range_lock::RepVecRangeLock [−][src]
pub struct RepVecRangeLock<T> { /* fields omitted */ }
Expand description
Interleaved multi-thread range lock for Vec<T>
.
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;
use std::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);
let thread0 = thread::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.
});
let thread1 = thread::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
});
let thread2 = thread::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
});
thread0.join();
thread1.join();
thread2.join();
// 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
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.
Unwrap the VecRangeLock into the contained data. This method consumes self.
Try to lock the given data slice at ‘cycle_offset’.
- On success: Returns a
RepVecRangeLockGuard
that can be used to access the locked region. IndexingRepVecRangeLockGuard
yields a slice of thedata
. - 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.