RepVecRangeLock

Struct RepVecRangeLock 

Source
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>

Source

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.
Source

pub fn data_len(&self) -> usize

Get the length (in number of elements) of the embedded Vec.

Source

pub fn into_inner(self) -> Vec<T>

Unwrap this RepVecRangeLock into the contained data. This method consumes self.

Source

pub fn try_lock( &'a self, cycle_offset: usize, ) -> TryLockResult<RepVecRangeLockGuard<'a, T>>

Try to lock the given data slice at ‘cycle_offset’.

Trait Implementations§

Source§

impl<T: Debug> Debug for RepVecRangeLock<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.