1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
extern crate shmem_bind;
use shmem_bind::{self as shmem, ShmemBox};
use std::error::Error;
use std::mem;
use std::process::Command;
#[derive(Debug)]
struct Message {
val: i32,
}
impl Drop for Message {
fn drop(&mut self) {
println!("message is dropping");
}
}
fn main() -> Result<(), Box<dyn Error>> {
// create new shared memory pointer with desired size
//
// first call to this function with the same FILE_LINK_ID would result in creating a new shared
// memory file and owning it. this would result in deleting the shared memory when the variable
// goes out of scope.
// the second call to this function will only open shared memory and would not delete it.
let shared_mem = shmem::Builder::new("shmem-example_message-passing.shm")
.with_size(mem::size_of::<Message>() as i64)
.open()?;
// wrap the raw shared memory ptr with desired Boxed type
// user must ensure that the data the pointer is pointing to is initialized and valid for use
let mut message = unsafe { shared_mem.boxed::<Message>() };
let mut args = std::env::args();
let num_args = args.len();
match num_args {
// parent process
1 => {
// ensure that first process owns the shared memory (used for cleanup)
let mut message = ShmemBox::own(message);
// initiate the data behind the boxed pointer
message.val = 1;
let binary_path = args.next().unwrap();
let new_val = 5;
// create new process to mutate the shared memory
let mut handle = Command::new(&binary_path)
.arg(format!("{new_val}"))
.spawn()
.unwrap();
handle.wait()?;
// assert that the new process mutated the shared memory
assert_eq!(message.val, new_val);
// message is dropped here, shared memory IS deallocated
}
// child process
2 => {
let value = std::env::args().last().unwrap().parse()?;
message.val = value;
// message is dropped here, shared memory IS NOT deallocated
}
_ => unimplemented!(),
}
Ok(())
}