lazy-init
lazy-init copied to clipboard
Would it be safe to add a way to mutate the value if it were only possible through a &mut reference?
Sorry if this is not the place to ask this question, but I was wondering if a version of LazyTransform
whose value could be mutated once initialized through an &mut
reference would somehow break the thread-safety?
I'm imagining an implementation along the lines of this:
pub fn get_or_create_mut<F>(&mut self, f: F) -> &mut U
where F: FnOnce(T) -> U
{
if !self.initialized.load(Ordering::Relaxed) {
let value = unsafe { &mut *self.value.get() };
let this = match value.take().unwrap() {
ThisOrThat::This(t) => t,
ThisOrThat::That(_) => panic!(),
};
*value = Some(ThisOrThat::That(f(this)));
self.initialized.store(true, Ordering::Relaxed);
}
self.extract_mut().unwrap()
}
fn extract_mut(&mut self) -> Option<&mut U> {
match unsafe { (*self.value.get()).as_mut() } {
None => None,
Some(&mut ThisOrThat::This(_)) => panic!(),
Some(&mut ThisOrThat::That(ref mut that)) => Some(that),
}
}
Intuitiviely, I imagine the &mut
reference would ensure there's no need for actual synchronization, but this stuff is tricky so I want to make sure. This isn't exactly a feature-request, though, since if it works, it's easy enough for me to implement on my own, so I hope you don't mind me using an issue to ask.
You could do something like that. std::sync::Mutex
has a get_mut
which functions on the same principle: that if you have an &mut
you are statically guaranteeing that nobody else is accessing the synchronized object.
I might quibble a bit with API design questions (like whether it makes sense to create the object/do the transform and then immediately mutate it) but the thread safety principle is sound.