orxfun / orx-split-vec

An efficient constant access time vector with dynamic capacity and pinned elements.
https://crates.io/crates/orx-split-vec
MIT License
2 stars 2 forks source link

Beautiful crate, but is it really `pinned`? #61

Open jymchng opened 1 week ago

jymchng commented 1 week ago

Hi @orxfun

Terrific work! I love what you're doing here, with SplitVec and FixedVec.

I just want to understand the pinned guarantees you claim. Since SplitVec is essentially a Vec<Vec<T>>, when a value of type SplitVec is moved, the owned Vec<Vec<T>> is moved as well, how would you guarantee that the data backing under std::alloc::RawVec is not moved?

Thank you.

orxfun commented 1 week ago

Hi @jymchng

Thanks a lot! And thanks for pointing to this subject. There are a few interesting perspectives on this, it would be great if you could share your opinions on them.

1. Should the guarantees include moves?

My initial thought on this was no. Because the idea was to use safe rust as much as possible. In this case it means using more of &T references and less of pointers *const T.

The starting point behind the pinned vectors was to make it safe and easy to hold on to references and use them. Since we cannot hold on to the references once we give away the ownership of the vector, I wasn't sure if this was really required. To make it clear:

use orx_split_vec::*;

fn take_ownership(vec: SplitVec<usize>) { }

let mut vec = SplitVec::new();
vec.push(42);
let rf = &vec[0];

take_ownership(vec);

// we cannot use rf anymore;
// do we need it to be correct?

However, on the way, I saw that there are one-step higher level useful data structures that can benefit from pinned vectors. And one way or the other, we use pointers in certain parts of the internal code.

So I think it must guarantee pinned elements even if the vector is moved.

2. Does it keep elements pinned on move?

As it was not on the initial plan, the repo might be lacking focus on this. But with your suggestion I added a simple test. It would be great if you could take a look.

https://github.com/orxfun/orx-split-vec/pull/62

https://github.com/orxfun/orx-split-vec/blob/test-pinned-elements-after-move/tests/pinned_on_move.rs

The tests pass, indicating that the elements stay pinned when we change the ownership of the vector. Of course, this does not prove.

To prove this, need to dive deeper in how the RawVec behaves on moves. I don't see a reason why it would allocate and copy the elements. But I am not expert on this. It would be great if you have an idea on this.

3. Do we really need Vec<Vec<_>>?

Actually, no. Using standard vector was very convenient at the beginning. Of course, moving away from it is a bit of refactoring and need to justify. Failing to keep elements pinned on move would certainly justify the effort.