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}