5

I have a struct that somehow must be retrieved in the form of raw pointer.

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

I need to write into its map field, so I dereference the raw pointer into struct, then try to write into its data field. But, I got the following error.

error[E0596]: cannot borrow immutable borrowed content `*map` as mutable
  --> examples/buffer.rs:34:5
   |
34 |     map[0] = 9;
   |     ^^^ cannot borrow as mutable

How do I make the map field mutable and writable?

The error is reproducible using the following code:

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;
}

Crate: memmap = "0.6.2"

Abdillah
  • 982
  • 11
  • 28
  • Have you read the documentation for [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) or the [`rc` module](https://doc.rust-lang.org/std/rc)? Have you tried a `Mutex`? – Shepmaster Feb 05 '18 at 02:32
  • Eh? This "...you cannot generally obtain a mutable reference to something inside an Rc" part is it? Well, I'm not register that one! I'll try `Mutex` and answer myself then. Thanks – Abdillah Feb 05 '18 at 02:40

1 Answers1

10

As @Shepmaster pointed out, Arc is immutable by design:

Shared references in Rust disallow mutation by default, and Arc is no exception: you cannot generally obtain a mutable reference to something inside an Arc. If you need to mutate through an Arc, use Mutex, RwLock, or one of the Atomic types.

I added a Mutex to fix the problem:

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

To access the field, I need to lock it first. I added an additional block to automatically unlock the Mutex when the block is done:

{
    let mut map = bdata.map.lock().unwrap();
    map[0] = 9;
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Abdillah
  • 982
  • 11
  • 28