Interior mutability on N f32's

In plain C, we can do something like:

  let *f = (float*) mallof(sizeof(float) * N)

and now, we have a pointer to a block of memory. This location of this block of memory does not change. The size of the block does not change. We can mutate the contents of the block as we wish.

==

In Rust, we have something like std::cell::Cell, which is great for interior mutability. If we only need to deal with one float, we can do std::cell::Cell<f32>.

However, in this particular case, we need the following:

  1. We need interior mutability on a contigious block of f32's.
  2. The size of the block is determined at alloc time, and never changes.

How do we achieve the above?

Context: We allocate a block of N f32's, we have a bunch of std::rc::Rc pointed to it -- we want to be able to mutate the interior contents of the block despite there being more than one Rc pointed at it.

Thanks!

You could use RefCell<Vec<f32>> and if you want to enforce that the size should never change after initialization you could use Vec::into_boxed_slice, then put it in a RefCell<Box<[f32]>>.

let mem = RefCell::new(vec![0.0; N].into_boxed_slice());

I’d do something like:

let rc: Rc<[Cell<f32>]> = vec![Default::default(); N].into();

Now you have an Rc of a slice, with interior mutability of each element.

2 Likes

Oh, that's even better!

1 Like

And, probably important to mention, there's no runtime overhead to the Cells.

1 Like

Yup, zero storage and access overhead. Although I almost like Cell more for zero panic probability :slight_smile:

1 Like

This was not mentioned in the original question.

Is there a way to convert this vec of cells to a *mut f32? (so I can pass it as an argument to BLAS) ?

Vec::as_mut_ptr

@RustyYato , @vitalyd , @birkenfeld : Everything makes sense now. Thanks everyone for the step-by-step explaination of how it all works.

2 Likes

No problem! :smile: