ruru 0.9.3

Native Ruby extensions in Rust
Documentation
use std::ptr;

use ruby_sys::thread;

use types::{CallbackPtr, c_void, Value};
use util;

#[cfg(unix)]
use types::RawFd;

use ::Object;

pub fn create<F, R>(func: F) -> Value
    where F: FnOnce() -> R,
          R: Object
{
    let fnbox = Box::new(func) as Box<FnOnce() -> R>;

    let closure_ptr = Box::into_raw(Box::new(fnbox)) as *mut c_void;

    unsafe { thread::rb_thread_create(thread_create_callbox::<R>, closure_ptr) }
}

#[cfg(unix)]
pub fn wait_fd(fd: RawFd) {
    unsafe { thread::rb_thread_wait_fd(fd) };
}

pub fn call_without_gvl<F, R, G>(func: F, unblock_func: Option<G>) -> R
    where F: FnOnce() -> R,
          G: FnOnce()
{
    unsafe {
        let ptr = if let Some(ubf) = unblock_func {
            thread::rb_thread_call_without_gvl(thread_call_callbox as CallbackPtr,
                                               util::closure_to_ptr(func),
                                               thread_call_callbox as CallbackPtr,
                                               util::closure_to_ptr(ubf))
        } else {
            thread::rb_thread_call_without_gvl(thread_call_callbox as CallbackPtr,
                                               util::closure_to_ptr(func),
                                               ptr::null() as CallbackPtr,
                                               ptr::null() as *const c_void)
        };

        util::ptr_to_data(ptr)
    }
}

pub fn call_without_gvl2<F, R, G>(func: F, unblock_func: Option<G>) -> R
    where F: FnOnce() -> R,
          G: FnOnce()
{
    unsafe {
        let ptr = if let Some(ubf) = unblock_func {
            thread::rb_thread_call_without_gvl2(thread_call_callbox as CallbackPtr,
                                                util::closure_to_ptr(func),
                                                thread_call_callbox as CallbackPtr,
                                                util::closure_to_ptr(ubf))
        } else {
            thread::rb_thread_call_without_gvl2(thread_call_callbox as CallbackPtr,
                                                util::closure_to_ptr(func),
                                                ptr::null() as CallbackPtr,
                                                ptr::null() as *const c_void)
        };

        util::ptr_to_data(ptr)
    }
}

pub fn call_with_gvl<F, R>(func: F) -> R
    where F: FnOnce() -> R
{
    unsafe {
        let ptr = thread::rb_thread_call_with_gvl(thread_call_callbox as CallbackPtr,
                                                  util::closure_to_ptr(func));

        util::ptr_to_data(ptr)
    }

}

extern "C" fn thread_create_callbox<R>(boxptr: *mut c_void) -> Value
    where R: Object
{
    let mut fnbox: Box<Box<FnMut() -> R>> =
        unsafe { Box::from_raw(boxptr as *mut Box<FnMut() -> R>) };

    fnbox().value()
}

extern "C" fn thread_call_callbox(boxptr: *mut c_void) -> *const c_void {
    let mut fnbox: Box<Box<FnMut() -> *const c_void>> =
        unsafe { Box::from_raw(boxptr as *mut Box<FnMut() -> *const c_void>) };

    fnbox()
}