如何使包含 Arc 的结构字段可写?

Abd*_*lah 4 immutability dereference rust raw-pointer

我有一个必须以原始指针形式检索的结构。

pub struct BufferData {
    /// Memory map for pixel data
    pub map: Arc<Box<memmap::MmapMut>>,
    pub otherdata: i32,
}
Run Code Online (Sandbox Code Playgroud)

我需要写入它的map字段,所以我将原始指针解引用到结构中,然后尝试写入它的数据字段。但是,我收到以下错误。

pub struct BufferData {
    /// Memory map for pixel data
    pub map: Arc<Box<memmap::MmapMut>>,
    pub otherdata: i32,
}
Run Code Online (Sandbox Code Playgroud)

如何使map字段可变和可写?

使用以下代码可重现该错误:

extern crate memmap;

use std::fs::File;
use std::sync::Arc;
use std::boxed::Box;
use std::ops::Deref;

pub struct BufferData {
    /// Memory map for pixel data
    pub map: Arc<Box<memmap::MmapMut>>,
    pub otherdata: i32,
}

fn main() -> () {
    // Somewhere on other module
    let mut mmap = Arc::new(Box::new(unsafe {
        memmap::MmapMut::map_mut(&File::open("./shm").expect("file")).expect("MmapMut")
    }));
    let mut bfr = BufferData {
        map: mmap,
        otherdata: 0,
    };
    let ptr: *const _ = &bfr;

    // Here, I must receive and process a pointer
    let mut bdata: &BufferData = unsafe { &*(ptr as *const BufferData) };
    let mut map = bdata.map.deref().deref();

    // Problem lies here: need to write into it, so need to be mutable
    map[0] = 9;
}
Run Code Online (Sandbox Code Playgroud)

箱: memmap = "0.6.2"

Abd*_*lah 9

正如@Shepmaster 指出的那样Arc在设计上是不可变的:

Rust 中的共享引用默认不允许突变,Arc也不例外:您通常无法获得对Arc. 如果通过需要发生变异Arc,使用MutexRwLock或者一个Atomic类型。

我添加了一个Mutex来解决问题:

pub struct BufferData {
    /// Memory map for pixel data
    pub map: Arc<Mutex<Box<memmap::MmapMut>>>,
    pub otherdata: i32,
}
Run Code Online (Sandbox Code Playgroud)

要访问该字段,我需要先锁定它。我添加了一个额外的块以Mutex在块完成时自动解锁:

{
    let mut map = bdata.map.lock().unwrap();
    map[0] = 9;
}
Run Code Online (Sandbox Code Playgroud)