Thank you both @2e71828 and @alice for your answers.
As I understand, both UnsafeCell
from that StackOverflow post and using a *mut T where T: Send
would be a "correct" way of sharing my bitvector mutably between threads. The UnsafeCell
would allow me to get a *mut T
, so let me treat both as a pointer. In contrast to my way of using a usize
to transfer the pointer, I am directly transferring the pointer. Sounds simple.
However you uncovered a problem in my code that goes a little bit beyond this: I am simply casting that mutable pointer to a mutable reference, and expect things to work. And things do work, because if the compiler would have optimised out any of the accesses to the bitvector, my algorithm would not terminate. So I must assume that even though there are multiple mutable references to the same bitvector, the compiler either did not notice, or it decided to do nothing about it. Still, it is a bit unnerving.
I would happily implement @2e71828's idea and simply stick with the pointer without ever converting it to a reference. However, the code that is using the bitvector is expecting a reference, and I would like it to stay that way. The code is a simple Dijkstra and has no reason to use pointers over references, or anything else unsafe. Also, it would be odd to copy and paste the code to make one variant with references, and one with pointers. So I really strongly believe that architecture-wise, the variant with violating Rusts borrowing laws is still the best.
But then, as you said, this is undefined behaviour, so potentially problematic. But would the compiler actually care? I have an intended race condition, which might cause errors, but I am aware and able to catch and fix them all. But if the compiler would compile the race condition in an unexpected way, that would break the program.
I feel like the open question is now if the compiler would actually perform different optimisations if it would know that a mutable or immutable reference can be mutated concurrently, or if it would ignore that.
If someone knows, please go ahead. But I will anyways ask about this on the internals forum, since there are likely more people that know the details.