use std::ffi::c_void;
use std::marker::PhantomData;
use std::ptr::NonNull;
use container_of::container_of;
use urcu_sys::RcuHead;
pub unsafe trait RcuCall {
fn configure<F>(self: Box<Self>, func: F)
where
F: FnOnce(NonNull<RcuHead>, unsafe extern "C" fn(head: *mut RcuHead));
}
pub struct RcuCallFn<F> {
func: F,
head: RcuHead,
}
impl<F> RcuCallFn<F> {
pub fn new(func: F) -> Box<Self> {
Box::new(Self {
func,
head: Default::default(),
})
}
unsafe extern "C" fn rcu_callback(head_ptr: *mut RcuHead)
where
F: FnOnce(),
{
let node = Box::from_raw(container_of!(head_ptr, Self, head));
(node.func)();
}
}
unsafe impl<F> RcuCall for RcuCallFn<F>
where
F: FnOnce(),
{
fn configure<P>(self: Box<Self>, func: P)
where
P: FnOnce(NonNull<RcuHead>, unsafe extern "C" fn(head: *mut RcuHead)),
{
let node_ptr = Box::into_raw(self);
let node = unsafe { &mut *node_ptr };
unsafe {
func(NonNull::new_unchecked(&mut node.head), Self::rcu_callback);
}
}
}
unsafe impl<F> Send for RcuCallFn<F> where F: Send {}
pub unsafe trait RcuDefer {
fn configure<F>(self: Box<Self>, func: F)
where
F: FnOnce(NonNull<c_void>, unsafe extern "C" fn(head: *mut c_void));
}
pub struct RcuDeferFn<F, C> {
func: F,
_context: PhantomData<*mut C>,
}
impl<F, C> RcuDeferFn<F, C> {
pub fn new(func: F) -> Box<Self> {
Box::new(Self {
func,
_context: PhantomData,
})
}
unsafe extern "C" fn callback(ptr: *mut c_void)
where
F: FnOnce(),
{
let node = Box::from_raw(ptr as *mut Self);
(node.func)();
}
}
unsafe impl<F, C> RcuDefer for RcuDeferFn<F, C>
where
F: FnOnce(),
{
fn configure<P>(self: Box<Self>, func: P)
where
P: FnOnce(NonNull<c_void>, unsafe extern "C" fn(head: *mut c_void)),
{
let ptr = Box::into_raw(self) as *mut c_void;
unsafe { func(NonNull::new_unchecked(ptr), Self::callback) }
}
}