Skip to main content

gc_alloc/
lib.rs

1use std::{cell::Cell, ffi::c_void};
2
3mod gc {
4    #![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, unused)]
5
6    include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
7}
8
9pub mod boxed;
10pub mod cstring;
11pub mod string;
12mod token;
13pub mod vec;
14
15pub use token::{GcToken, ThreadGuard, ThreadToken};
16
17thread_local! {
18    static GC_REGISTERED: Cell<bool> = const { Cell::new(false) };
19}
20
21pub fn init() -> ThreadToken {
22    unsafe {
23        gc::GC_init();
24        gc::GC_allow_register_threads();
25    }
26
27    GC_REGISTERED.set(true);
28
29    ThreadToken::new()
30}
31
32pub fn init_thread() -> ThreadGuard {
33    assert!(
34        unsafe { gc::GC_thread_is_registered() } == 0,
35        "Thread is already registered with the GC. "
36    );
37
38    unsafe extern "C" fn do_register(sb: *mut gc::GC_stack_base, _: *mut c_void) -> *mut c_void {
39        let result = unsafe { gc::GC_register_my_thread(sb) };
40        assert!(
41            result == gc::GC_SUCCESS as i32,
42            "Failed to register thread with GC. Error code: {}",
43            result
44        );
45        std::ptr::null_mut()
46    }
47
48    unsafe { gc::GC_call_with_stack_base(Some(do_register), std::ptr::null_mut()) };
49
50    GC_REGISTERED.set(true);
51
52    ThreadGuard::new()
53}
54
55mod private {
56    pub trait Sealed {}
57}