简体   繁体   中英

Convert Arc<RwLock> to &mut

I am trying to have a value in a trait that can be mutated by means of a reference. The problem is that the String values are very large and may be accessed by many threads, so my solution looks something like this:

trait MyTrait {
    fn name<'a>(&'a mut self) -> &'a mut String;
}

struct SimpleImpl {
    name: String
}

impl MyTrait for SimpleImpl {
    fn name<'a>(&'a mut self) -> &'a mut String {
        &mut self.name
    }
}

use std::sync::{Arc,RwLock};

struct ParallelImpl {
    name: Arc<RwLock<String>>
}

impl MyTrait for ParallelImpl {
    fn name<'a>(&'a mut self) -> &'a mut String {
        self.name.get_mut().unwrap()
    }
}

fn main() {
    let mut a = SimpleImpl { name: String::from("simple") };
    let mut b = ParallelImpl { name: Arc::new(RwLock::new(String::from("parallel"))) };

    a.name().as_mut_str();
    b.name().as_mut_str();
}

This fails to compile with

main2.rs:23:9: 23:18 error: cannot borrow immutable borrowed content as mutable
main2.rs:23         self.name.get_mut().unwrap()

Why can't I call get_mut() to unwrap both the Arc and the RwLock ?

Have a better look at the interface of RwLock .

get_mut returns a LockResult<&mut T> which is a guard object. The destruction of this guard automatically unlocks the lock.

In order for things to be safe, the &mut T that you get by calling unwrap() on the guard is borrowing from the guard , that is, the lifetime of the result of unwrap() is limited by that of the guard (since after the guard is destroyed, the lock is unlocked).

And here, you are creating a temporary guard and throwing it away immediately, so the lifetime of the reference cannot exceed that of the function...

Congratz to Rust! Yet another data race prevented at compile-time :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM