#maybe get ref or mut ref to a value stored inside Arc Mutex Option T

32 messages · Page 1 of 1 (latest)

oblique kite
#

hi folks! I am wondering if it is possible to maybe get a ref or a mut ref to a value stored inside an Arc<Mutex<Option<T>>>

I know I can get a MutexGuard<'a, Option<T>> by calling self.0.lock()

However, if I call self.0.lock().as_ref().unwrap(), or self.0.lock().as_mut().unwrap() in get and get_mut respectively, the MutexGuard is not maintained when passing out of the function.

What can be done in this situation? I would like for the lock to be maintained, if possible.

Am I making some kind of conceptual error here?

when I say maybe get a ref, what I mean is that I want the function to unwrap the option (or at least reroute somehow if the option is not available)

This is mainly to avoid having to call .lock().as_ref().unwrap() on every access to the underlying T.
I would rather be able to simply call .get() or .get_mut() depending on the usage

I have the following: ```rust
#[derive(Default)]
pub struct Amo<T>(Arc<Mutex<Option<T>>>);

impl<T> Amo<T> {
delegate!{
to self.0.lock() {
pub fn is_some(&self) -> bool;
pub fn is_none(&self) -> bool;
}
}

pub fn get<'a>(&'a self) -> MutexGuard<'a, &T> {
    todo!();
}

pub fn get_mut<'a>(&'a mut self) -> MutexGuard<'a, &'a mut T> {
    todo!();
}

}

#

This question basically reduces to:

how can I get a MutexGuard<&T> or a MutexGuard<&mut T> from a MutexGuard<Option<T>>

#

I am wondering if maybe it should actually be an Arc<Option<Mutex<T>>> instead of an Arc<Mutex<Option<T>>>

vernal bridge
#

Using libstd's mutex, you can't do that.

Using parking_lot's mutex, the MutexGuard has a map method that returns a MappedMutexGuard. You should be able to use it as MutexGuard::map(guard, |g| g.as_mut().unwrap()). They also have a try_map, if you'd rather handle the error rather than unwrap. Note the return type is MappedMutexGuard

Arc<Option<Mutex<T>>> means something slightly different, but it might still work. In that case, you'd still have the issue that MutexGuard<T> can't become MutexGuard<&mut T>, tho.

oblique kite
#

nice! I didn't know about MappedMutexGuard

#

right now, I am basically working out the differences between Arc Option Mutex, Arc Mutex Option, Option Arc Mutex

#

they all mean slightly different things, as you mentioned

#

it looks like I want the Arc to be the outer layer for sure

#

maybe not in all cases, but i think it makes for clearer semantics

#

basically because what I ultimately want is Arc usage semantics

#

the next question is about what the interior should look like

#

I suppose it is somewhat obvious what the differences are

#

ie, Option<Mutex<T>> means we might have a Mutex<T>

#

Mutex<Option<T>> means we do have something we can lock that maybe contains a T

#

it seems Arc<Mutex<Option<T>>> is probably the one I want

#

I suppose there are different semantics of when and where we can flip between None and Some

#

and what the guarantees are

#

ie, if Option is the innermost, it implies that any state change must be protected

#

instead, if we have Option<Mutex<T>>, I suppose some holder could just decide not to track it anymore

#

but that seems a bit odd right now to me

#

it seems like that clashes a bit with the intent of using an Arc

#

because Arc<Mutex more or less means we are reference counting who is holding the mutex

#

allowing there to be an inner Option seems to muddle these semantics

#

im not sure if it actually makes a difference in practice

#

but having Arc<Option<Mutex<T>>> seems to mean that the reference count of the Arc is an upper bound on the number of users of the mutex, with some of them possibly not holding it anymore

#

which seems like is asking for bugs

#

but im not quite sure

#

i havn't tried all of these things yet, just attempting to reason outwards from my current level of understanding

#

it seems like in that case, the mutex might get switched interior to the outer Arc layer, which seems to massively confuse the meaning of the reference count

#

in other words, if you have three arc<option<mutex<t>>>> all handles of a common mutex, and then you switch one of the inner option<mutex<t>> to be Some(other_mutex)

it seems to be asking for bugs unless the compiler disallows it

#

all in all, it seems like Arc<Mutex<Option<T>>> is probably the one with the most sane semantics. I am already using parking_lot and will check out MappedMutexGuard! thanks!

TL;DR, thank you!! I think I am probably clear on which to use, but still appreciate any other insights!

past basin
# oblique kite but having Arc<Option<Mutex<T>>> seems to mean that the reference count of the A...

It would mean that the Option<Mutex> has shared ownership. All that means is that they all own the same thing, and that it gets dropped whenever all the owners drop their reference to it. You can never mutate something inside an Arc if it is not interior mutable. An Option is not interior mutable. In other words: you would either have a None or Some from the start until the Arc is dropped. Which is why you almost never see this in practice.