Skip to main content

gc_alloc/
boxed.rs

1use std::{ffi::c_void, ptr::NonNull};
2
3use crate::{GcToken, gc};
4
5pub fn alloc<T>(_token: &impl GcToken, val: T) -> &'static mut T {
6    let ptr =
7        unsafe { gc::GC_memalign(std::mem::size_of::<T>(), std::mem::align_of::<T>()) as *mut T };
8    let mut ptr = NonNull::new(ptr).expect("GC_malloc failed");
9    unsafe { ptr.write(val) };
10
11    register_finalizer(ptr.as_ptr());
12    unsafe { ptr.as_mut() }
13}
14
15fn register_finalizer<T>(ptr: *mut T) {
16    if std::mem::needs_drop::<T>() {
17        extern "C" fn finalizer<T>(obj: *mut c_void, _: *mut c_void) {
18            let ptr = obj as *mut T;
19            unsafe { std::ptr::drop_in_place(ptr) };
20        }
21
22        unsafe {
23            gc::GC_register_finalizer(
24                ptr as *mut std::ffi::c_void,
25                Some(finalizer::<T>),
26                std::ptr::null_mut(),
27                std::ptr::null_mut(),
28                std::ptr::null_mut(),
29            );
30        }
31    }
32}