use std::time::Duration;
use std::ptr;
use std::ffi::CString;
use std::ffi::CStr;
use libc::*;
pub type LogicalProcessContext = c_void;
#[derive(Clone)]
pub enum LogicalProcessThread {
SingleThread,
FunneledThread
}
#[derive(Clone)]
pub struct LogicalProcessParameters {
pub name: String,
pub lookahead: f64,
pub lookahead_time_test_threshold: usize,
pub sync_timeout: Duration,
pub initializing_timeout: Duration,
pub idle_loop_interval: Option<Duration>,
pub network_test_interval: Duration,
pub network_test_threshold: usize,
pub network_wait_threshold: usize,
pub thread_mode: LogicalProcessThread
}
impl LogicalProcessParameters {
pub fn new(lookahead: f64) -> LogicalProcessParameters {
LogicalProcessParameters {
name: String::from("LP"),
lookahead: lookahead,
lookahead_time_test_threshold: 1000,
sync_timeout: Duration::from_secs(60),
initializing_timeout: Duration::from_secs(10),
idle_loop_interval: None,
network_test_interval: Duration::from_millis(10),
network_test_threshold: 256,
network_wait_threshold: 8192,
thread_mode: LogicalProcessThread::SingleThread
}
}
}
#[repr(C)]
pub struct LogicalProcessParametersRepr {
delete_repr: unsafe extern "C" fn(*mut LogicalProcessParametersRepr),
name: *mut c_char,
delete_name: unsafe extern "C" fn(*mut c_char),
lookahead: f64,
lookahead_time_test_threshold: usize,
sync_timeout: [u8; 16],
initializing_timeout: [u8; 16],
idle_loop_interval: [u8; 16],
idle_loop_interval_defined: c_int,
network_test_interval: [u8; 16],
network_test_threshold: usize,
network_wait_threshold: usize,
thread_mode: c_int
}
impl LogicalProcessParametersRepr {
pub fn new(ps: LogicalProcessParameters) -> Self {
let name = CString::new(ps.name.clone()).expect("NulError");
let name = CString::into_raw(name);
LogicalProcessParametersRepr {
delete_repr: delete_lp_repr,
name: name,
delete_name: delete_lp_name,
lookahead: ps.lookahead,
lookahead_time_test_threshold: ps.lookahead_time_test_threshold,
sync_timeout: u128::to_ne_bytes(ps.sync_timeout.as_nanos()),
initializing_timeout: u128::to_ne_bytes(ps.initializing_timeout.as_nanos()),
idle_loop_interval: u128::to_ne_bytes(ps.idle_loop_interval.unwrap_or(Duration::from_micros(3)).as_nanos()),
idle_loop_interval_defined: if ps.idle_loop_interval.is_some() { 1 } else { 0 },
network_test_interval: u128::to_ne_bytes(ps.network_test_interval.as_nanos()),
network_test_threshold: ps.network_test_threshold,
network_wait_threshold: ps.network_wait_threshold,
thread_mode: {
match ps.thread_mode {
LogicalProcessThread::SingleThread => 0,
LogicalProcessThread::FunneledThread => 1
}
}
}
}
}
impl Drop for LogicalProcessParametersRepr {
fn drop(&mut self) {
unsafe {
(self.delete_name)(self.name);
}
}
}
unsafe extern "C" fn delete_lp_name(name: *mut c_char) {
if name != ptr::null_mut() {
let _ = CString::from_raw(name);
}
}
unsafe extern "C" fn delete_lp_repr(e: *mut LogicalProcessParametersRepr) {
if e != ptr::null_mut() {
let _ = Box::from_raw(e);
}
}
pub unsafe fn ffi_logical_process_parameters_repr_into(ps: *mut LogicalProcessParametersRepr) -> LogicalProcessParameters {
let name = CStr::from_ptr((*ps).name);
let name = name.to_bytes().to_vec();
let name = String::from_utf8(name).expect("FromUtf8Error");
let xs = LogicalProcessParameters {
name: name,
lookahead: (*ps).lookahead,
lookahead_time_test_threshold: (*ps).lookahead_time_test_threshold,
sync_timeout: Duration::from_nanos(u128::from_ne_bytes((*ps).sync_timeout) as u64),
initializing_timeout: Duration::from_nanos(u128::from_ne_bytes((*ps).initializing_timeout) as u64),
idle_loop_interval: if (*ps).idle_loop_interval_defined != 0 { Some(Duration::from_nanos(u128::from_ne_bytes((*ps).idle_loop_interval) as u64)) } else { None },
network_test_interval: Duration::from_nanos(u128::from_ne_bytes((*ps).network_test_interval) as u64),
network_test_threshold: (*ps).network_test_threshold,
network_wait_threshold: (*ps).network_wait_threshold,
thread_mode: {
if (*ps).thread_mode != 0 { LogicalProcessThread::FunneledThread } else { LogicalProcessThread::SingleThread }
}
};
((*ps).delete_repr)(ps);
xs
}