Function syncpool::make_box[][src]

pub fn make_box<T, F: Fn(Box<T>) -> Box<T>>(packer: F) -> Box<T>

This API is a wrapper on the unsafer version of the direct-to-the-heap-box APIs. The API is safe because it is the caller's responsiblity to supply the struct initialier as a closure, such that after calling the struct initializer, the returned object shall be valid and meaningful.

The closure will take the raw box object as the input parameter, which maybe invalid, and it is the closure's responsiblity to assign valid values to the fields.

Examples

Create the dangerous struct and pack valid values with it.

use syncpool::{raw_box_zeroed, make_box};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::sync::atomic::{AtomicBool, Ordering};

struct BigStruct {
    a: u32,
    b: u32,
    c: [u8; 0x1_000_000],
}

struct DangerousStruct {
    a: u32,
    b: MaybeUninit<AtomicBool>,
    c: NonNull<BigStruct>,
}

// create the object directly on the heap
let mut boxed: Box<DangerousStruct> = make_box(|mut src: Box<DangerousStruct>| {
    // initialize the fields in the handler
    let mut big: &mut BigStruct = unsafe { Box::leak(raw_box_zeroed::<BigStruct>()) };
    big.a = 42;
    big.b = 4 * 42;
    big.c[4200] = 125;

    // make sure we initialize the fields
    src.a = 42;
    src.b = MaybeUninit::new(AtomicBool::new(false));
    src.c = NonNull::new(big).unwrap();

    src
});

// the fields are now valid
let big_ref = unsafe { boxed.c.as_ref() };

assert_eq!(big_ref.c.len(), 0x1_000_000);
assert_eq!(big_ref.c[4200], 125);
assert_eq!(big_ref.a, 42);
assert_eq!(big_ref.b, 168);