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}