#slice #thread #reference #share #adapter #mutable #sharing

bin+lib slice_adapter

Utility to help share slice between thread

1 unstable release

0.1.1 Apr 4, 2024
0.1.0 Apr 4, 2024

#35 in #mutable

MIT license

7KB
91 lines

A simple utility to help share slice between thread.

Slice Adapter

This library provides a SliceAdapter struct that can be used to share references to slices across threads.

SliceAdapter

The SliceAdapter stores the pointer and length of a slice. It implements Send to allow passing between threads.

#[derive(Clone, Copy)]  
pub struct SliceAdapter {
  pointer: usize,
  length: usize
}

unsafe impl Send for SliceAdapter {}

SliceAdapter can be constructed from mutable and immutable slice references using the From trait.

impl<T> From<&mut [T]> for SliceAdapter {
  //...
}

impl<T> From<&[T]> for SliceAdapter {
  //...  
}

And converted back using From.

impl<T> From<SliceAdapter> for &mut [T] {
  //...
}

impl<T> From<SliceAdapter> for &[T] {
  //...
}

Examples

The tests demonstrate sharing mutable slice references across threads using SliceAdapter.

In this example, three threads each modify a different element of the slice:

#[test]
fn test_adapter_for_mut_1() {
    let mut a = [1, 2, 3, 4, 5];

    let adapter = Arc::new(Mutex::new(SliceAdapter::from(&mut a[..])));
    let adapter2 = adapter.clone();
    let adapter3 = adapter.clone();

    let handle1 = std::thread::spawn(move || {
        let adapter: SliceAdapter = *(adapter2.lock().unwrap());
        let slice: &mut [i32] = adapter.into();
        slice[0] = 10;
    });

    let handle2 = std::thread::spawn(move || {
        let adapter: SliceAdapter = *(adapter3.lock().unwrap());
        let slice: &mut [i32] = adapter.into();
        slice[1] = 20;
    });

    {
        let adapter: SliceAdapter = *(adapter.lock().unwrap());
        let slice: &mut [i32] = adapter.into();
        slice[2] = 30;
    }

    handle1.join().unwrap();
    handle2.join().unwrap();

    assert_eq!(a, [10, 20, 30, 4, 5]);
}

#[test]
fn test_adapter_for_mut_2() {
    let mut a = [1, 2, 3, 4, 5];

    let adapter1 = SliceAdapter::from(&mut a[..1]);
    let adapter2 = SliceAdapter::from(&mut a[1..2]);

    let handle1 = std::thread::spawn(move || {
        let slice: &mut [i32] = adapter1.into();
        slice[0] = 10;
    });

    let handle2 = std::thread::spawn(move || {
        let slice: &mut [i32] = adapter2.into();
        slice[0] = 20;
    });

    {
        a[2] = 30;
    }

    handle1.join().unwrap();
    handle2.join().unwrap();

    assert_eq!(a, [10, 20, 30, 4, 5]);
}

No runtime deps