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()

.

+3


source to share


2 answers


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.

+3


source


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());

      

+4


source







All Articles