1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
use {
std::{
collections::{VecDeque},
time::Instant,
mem,
os::raw::{c_int},
ptr,
},
self::super::{
libc_sys,
},
};
#[derive(Clone, Copy)]
pub struct SelectTimer {
id: u64,
timeout: f64,
repeats: bool,
delta_timeout: f64,
}
pub struct SelectTimers {
//pub signal_fds: [c_int; 2],
pub timers: VecDeque<SelectTimer>,
pub time_start: Instant,
pub select_time: f64,
}
impl SelectTimers {
pub fn new() -> Self {
Self {
timers: Default::default(),
time_start: Instant::now(),
select_time: 0.0
}
}
pub fn select(&mut self, fd: c_int) {
let mut fds = mem::MaybeUninit::uninit();
unsafe {
libc_sys::FD_ZERO(fds.as_mut_ptr());
libc_sys::FD_SET(0, fds.as_mut_ptr());
libc_sys::FD_SET(fd, fds.as_mut_ptr());
}
//libc_sys::FD_SET(self.signal_fds[0], fds.as_mut_ptr());
// If there are any timers, we set the timeout for select to the `delta_timeout`
// of the first timer that should be fired. Otherwise, we set the timeout to
// None, so that select will block indefinitely.
let timeout = if let Some(timer) = self.timers.front() {
Some(libc_sys::timeval {
// `tv_sec` is in seconds, so take the integer part of `delta_timeout`
tv_sec: timer.delta_timeout.trunc() as libc_sys::time_t,
// `tv_usec` is in microseconds, so take the fractional part of
// `delta_timeout` 1000000.0.
tv_usec: (timer.delta_timeout.fract() * 1000000.0) as libc_sys::time_t,
})
}
else {
None
};
let _nfds = unsafe {libc_sys::select(
fd+1,
fds.as_mut_ptr(),
ptr::null_mut(),
ptr::null_mut(),
if let Some(mut timeout) = timeout {&mut timeout} else {ptr::null_mut()}
)};
// println!("RETURNED!");
}
pub fn time_now(&self) -> f64 {
let time_now = Instant::now(); //unsafe {mach_absolute_time()};
(time_now.duration_since(self.time_start)).as_micros() as f64 / 1_000_000.0
}
pub fn update_timers(&mut self, out: &mut Vec<u64>) {
out.clear();
let last_select_time = self.select_time;
self.select_time = self.time_now();
let mut select_time_used = self.select_time - last_select_time;
//println!("{}", self.timers.len());
while let Some(timer) = self.timers.front_mut() {
// If the amount of time that elapsed is less than `delta_timeout` for the
// next timer, then no more timers need to be fired.
// println!("TIMER COMPARE {} {}", select_time_used, timer.delta_timeout);
if select_time_used < timer.delta_timeout {
timer.delta_timeout -= select_time_used;
break;
}
let timer = *self.timers.front().unwrap();
select_time_used -= timer.delta_timeout;
// Stop the timer to remove it from the list.
self.stop_timer(timer.id);
// If the timer is repeating, simply start it again.
if timer.repeats {
self.start_timer(timer.id, timer.timeout, timer.repeats);
}
out.push(timer.id);
}
}
pub fn start_timer(&mut self, id: u64, timeout: f64, repeats: bool) {
//println!("STARTING TIMER {:?} {:?} {:?}", id, timeout, repeats);
// Timers are stored in an ordered list. Each timer stores the amount of time between
// when its predecessor in the list should fire and when the timer itself should fire
// in `delta_timeout`.
// Since we are starting a new timer, our first step is to find where in the list this
// new timer should be inserted. `delta_timeout` is initially set to `timeout`. As we move
// through the list, we subtract the `delta_timeout` of the timers preceding the new timer
// in the list. Once this subtraction would cause an overflow, we have found the correct
// position in the list. The timer should fire after the one preceding it in the list, and
// before the one succeeding it in the list. Moreover `delta_timeout` is now set to the
// correct value.
let mut delta_timeout = timeout;
let index = self.timers.iter().position( | timer | {
if delta_timeout < timer.delta_timeout {
return true;
}
delta_timeout -= timer.delta_timeout;
false
}).unwrap_or(self.timers.len());
// Insert the timer in the list.
//
// We also store the original `timeout` with each timer. This is necessary if the timer is
// repeatable and we want to restart it later on.
self.timers.insert(
index,
SelectTimer {
id,
timeout,
repeats,
delta_timeout,
},
);
// The timer succeeding the newly inserted timer now has a new timer preceding it, so we
// need to adjust its `delta_timeout`.
//
// Note that by construction, `timer.delta_timeout < delta_timeout`. Otherwise, the newly
// inserted timer would have been inserted *after* the timer succeeding it, not before it.
if index < self.timers.len() - 1 {
let timer = &mut self.timers[index + 1];
// This computation should never underflow (see above)
timer.delta_timeout -= delta_timeout;
}
}
pub fn stop_timer(&mut self, id: u64) {
//println!("STOPPING TIMER {:?}", id);
// Since we are stopping an existing timer, our first step is to find where in the list this
// timer should be removed.
let index = if let Some(index) = self.timers.iter().position( | timer | timer.id == id) {
index
} else {
return;
};
// Remove the timer from the list.
let delta_timeout = self.timers.remove(index).unwrap().delta_timeout;
// The timer succeeding the removed timer now has a different timer preceding it, so we need
// to adjust its `delta timeout`.
if index < self.timers.len() {
self.timers[index].delta_timeout += delta_timeout;
}
}
}