lucchetto 0.4.0

easily call a rust function without holding the GVL lock
Documentation
pub extern crate paste;
pub extern crate rb_sys;
pub extern crate static_assertions;

use std::{sync::Arc, rc::Rc};

pub use lucchetto_macros::without_gvl;

pub trait GvlSafe {}

macro_rules! impl_safe {
    ($($ty:ty),+) => {
        $(
            impl GvlSafe for $ty {}
        )+
    };
}

impl_safe!(String, i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, usize, &str);

macro_rules! impl_safe_1_ty {
    ($($ty:ty),+) => {
        $(
            impl<T: GvlSafe> GvlSafe for $ty {}
        )+
    };
}

impl<T: GvlSafe> GvlSafe for &[T] {}
impl_safe_1_ty!(Vec<T>, Arc<T>, Rc<T>, Box<T>, Option<T>);

#[macro_export]
macro_rules! call_without_gvl {
    ($func:expr, args: ($($arg:expr, $ty:ty),+), return_type: $return_ty:ty) => {
        {
            lucchetto::paste::paste! {
                let mut result: Option<$return_ty> = None;
                $(lucchetto::static_assertions::assert_impl_all!($ty: lucchetto::GvlSafe);)+
                lucchetto::static_assertions::assert_impl_all!($return_ty: lucchetto::GvlSafe);
                let data: ( $($ty,)+ &mut Option<$return_ty> ) = ($($arg,)+ &mut result);

                let data_ptr: *mut std::ffi::c_void = &data as *const _ as *mut _;
                std::mem::forget(data);

                unsafe extern "C" fn __decl_macro_anon_wrapper(data: *mut std::ffi::c_void) -> *mut std::ffi::c_void {
                        let data = data as *mut ( $($ty,)+ &mut Option<$return_ty> );

                        let ( $([<__ $arg _name>],)+ result_output) = data.read();
                        let result = $func( $( [<__ $arg _name>], )+);
                        *result_output = Some(result);
                        std::ptr::null_mut()
                    }

                unsafe {
                    lucchetto::rb_sys::rb_thread_call_without_gvl(Some(__decl_macro_anon_wrapper), data_ptr, None, std::ptr::null_mut());
                }
                result.unwrap()
            }
        }
    };
}