How to make a method that does not require volatile self-management for locked Mutex?
Recognition of the field structure for reading rusty playpen :
use std::sync::Mutex;
#[deriving(Show)]
struct Test{
a: uint,
}
impl Test{
fn new() -> Test{
Test { a: 0}
}
fn get(&self) -> uint {
self.a
}
}
fn main() {
let t = Test{a: 42};
let m = Mutex::new(Test::new());
println!("Getting t: {} where t.a = {}", t.get(), t.a);
{
let m2 = m.lock();
println!("m2.a = {}", m2.a); // works
//println!("m2.get() = {}", m2.get()); // error: cannot borrow immutable local variable `m2` as mutable
}
}
So, in this case, accessing the field works m2.a
, but the call m2.get()
requires it to m2
be mutable, even though get does not mutate anything and is not declared to mutate anything, especially not &self
.
To make this code work, I could just declare m2
with let mut m2 = m.lock();
and everything works fine, but why do I need it here and there is a better way to call m2.get()
without declaring m2
mutable in similar to how it works for t
which I declare as non-mutable and which still lets me call t.get()
.
source to share
This is due to a slight limitation of the feature family Deref
right now, namely: the implementation of both Deref
and DerefMut
for the same type is now slightly broken due to the behavior of autoderef for methods, namely, deref_mut
it is always called, even to get references &
.
As a result, MutexGuard
you need to change for you to call the methods that you require &self
. Typically immutable uses Mutex
are rare, but RWLock
one that supports both read and write locks separately is better suited for this use case because it allows concurrent read locks.
source to share
Yes, the compiler prefers to name deref_mut
more deref
if available. In your case, it deref
will suffice and work, but the implicit dereference mechanism picks deref_mut
instead and then complains about m2
not being mutable.
To add to what reem said, the lock object implements both deref
, DerefMut
and if you don't need mutable borrowing, you can get immutable by explicitly reconfiguring it to be immutable:
println!("m2.get() = {}", (&*m2).get());
and if you need this kind of access, you can also write
let m2 = m.lock();
let m2 = &*m2;
which then allows
println!("m2.get() = {}", m2.get());
source to share