use std::convert::*;
use std::mem;
use libc::*;
use dvcompute_network::network::*;
use crate::simulation::comm::pid::LogicalProcessId;
use crate::simulation::comm::context::*;
pub struct LogicalProcess {}
impl LogicalProcess {
pub fn run<F>(network: NetworkSupport, pids: &[LogicalProcessId], ps: LogicalProcessParameters, f: F)
where F: FnOnce(&LogicalProcessContext) + Send + 'static
{
unsafe {
let ps = LogicalProcessParametersRepr::new(ps);
let ps = Box::new(ps);
let ps = Box::into_raw(ps);
let f = LogicalProcessBox::new(f);
let f = LogicalProcessRepr::into_repr(f);
let pids: Vec<c_int> = pids.iter().map(|x| x.rank()).collect();
let pid_ptr = pids.as_ptr();
let pid_count = pids.len().try_into().unwrap();
run_extern_logical_process(network, pid_ptr, pid_count, ps, f)
}
}
}
#[must_use = "computations are lazy and do nothing unless to be run"]
pub struct LogicalProcessBox {
f: Box<dyn LogicalProcessFnBox>
}
impl LogicalProcessBox {
#[doc(hidden)]
#[inline]
pub fn new<F>(f: F) -> Self
where F: FnOnce(&LogicalProcessContext) + Send + 'static
{
LogicalProcessBox {
f: Box::new(f)
}
}
#[doc(hidden)]
#[inline]
pub fn call_box(self, arg: (&LogicalProcessContext,)) {
let LogicalProcessBox { f } = self;
f.call_box(arg)
}
}
trait LogicalProcessFnBox {
fn call_box(self: Box<Self>, args: (&LogicalProcessContext,));
}
impl<F> LogicalProcessFnBox for F
where F: for<'a> FnOnce(&'a LogicalProcessContext)
{
fn call_box(self: Box<Self>, args: (&LogicalProcessContext,)) {
let this: Self = *self;
this(args.0)
}
}
#[repr(C)]
#[derive(Copy, Clone)]
struct LogicalProcessTraitObject {
field1: *mut c_void,
field2: *mut c_void
}
#[repr(C)]
pub struct LogicalProcessRepr {
delete: unsafe extern "C" fn(obj: *mut LogicalProcessTraitObject),
callback: unsafe extern "C" fn(obj: *mut LogicalProcessTraitObject, p: *const LogicalProcessContext),
trait_object: LogicalProcessTraitObject
}
impl Drop for LogicalProcessRepr {
fn drop(&mut self) {
unsafe {
(self.delete)(&mut self.trait_object);
}
}
}
impl LogicalProcessRepr {
#[inline]
pub fn into_repr(comp: LogicalProcessBox) -> LogicalProcessRepr {
unsafe {
LogicalProcessRepr {
delete: delete_lp_repr,
callback: call_lp_repr,
trait_object: mem::transmute(comp)
}
}
}
#[inline]
fn _call_repr(mut self, ctx: &LogicalProcessContext) {
unsafe {
(self.callback)(&mut self.trait_object, ctx);
mem::forget(self);
}
}
}
unsafe extern "C" fn call_lp_repr(comp: *mut LogicalProcessTraitObject, ctx: *const LogicalProcessContext) {
let comp: LogicalProcessBox = mem::transmute(*comp);
comp.call_box((&*ctx,))
}
unsafe extern "C" fn delete_lp_repr(comp: *mut LogicalProcessTraitObject) {
let _: LogicalProcessBox = mem::transmute(*comp);
}
unsafe impl Send for LogicalProcessBox {}
unsafe impl Send for LogicalProcessRepr {}
#[cfg(all(feature="cons_mode", not(feature="cons_core_mode")))]
#[cfg_attr(windows, link(name = "dvcompute_core_cons.dll"))]
#[cfg_attr(not(windows), link(name = "dvcompute_core_cons"))]
extern {
#[doc(hidden)]
pub fn run_extern_logical_process(network: NetworkSupport, ranks: *const c_int, rank_count: c_int,
ps: *mut LogicalProcessParametersRepr, f: LogicalProcessRepr);
}
#[cfg(all(feature="cons_mode", feature="cons_core_mode"))]
extern {
#[doc(hidden)]
pub fn run_extern_logical_process(network: NetworkSupport, ranks: *const c_int, rank_count: c_int,
ps: *mut LogicalProcessParametersRepr, f: LogicalProcessRepr);
}