Runtime removal: refactor timer
This patch continues runtime removal by moving out timer-related code into `sys`. Because this eliminates APIs in `libnative` and `librustrt`, it is a: [breaking-change] This functionality is likely to be available publicly, in some form, from `std` in the future.
This commit is contained in:
parent
0f98e75b69
commit
b8f1193bb1
@ -29,19 +29,6 @@ use std::os;
|
||||
use std::rt::rtio::{mod, IoResult, IoError};
|
||||
use std::num;
|
||||
|
||||
#[cfg(any(target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "android",
|
||||
target_os = "linux"))]
|
||||
#[path = "timer_unix.rs"]
|
||||
pub mod timer;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[path = "timer_windows.rs"]
|
||||
pub mod timer;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[path = "tty_windows.rs"]
|
||||
mod tty;
|
||||
@ -112,10 +99,6 @@ impl IoFactory {
|
||||
}
|
||||
|
||||
impl rtio::IoFactory for IoFactory {
|
||||
// misc
|
||||
fn timer_init(&mut self) -> IoResult<Box<rtio::RtioTimer + Send>> {
|
||||
timer::Timer::new().map(|t| box t as Box<rtio::RtioTimer + Send>)
|
||||
}
|
||||
#[cfg(unix)]
|
||||
fn tty_open(&mut self, fd: c_int, _readable: bool)
|
||||
-> IoResult<Box<rtio::RtioTTY + Send>> {
|
||||
|
@ -21,10 +21,9 @@ and create receivers which will receive notifications after a period of time.
|
||||
|
||||
use comm::{Receiver, Sender, channel};
|
||||
use time::Duration;
|
||||
use io::{IoResult, IoError};
|
||||
use kinds::Send;
|
||||
use boxed::Box;
|
||||
use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
|
||||
use io::IoResult;
|
||||
use sys::timer::Callback;
|
||||
use sys::timer::Timer as TimerImp;
|
||||
|
||||
/// A synchronous timer object
|
||||
///
|
||||
@ -69,7 +68,7 @@ use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Timer {
|
||||
obj: Box<RtioTimer + Send>,
|
||||
inner: TimerImp,
|
||||
}
|
||||
|
||||
struct TimerCallback { tx: Sender<()> }
|
||||
@ -90,9 +89,7 @@ impl Timer {
|
||||
/// for a number of milliseconds, or to possibly create channels which will
|
||||
/// get notified after an amount of time has passed.
|
||||
pub fn new() -> IoResult<Timer> {
|
||||
LocalIo::maybe_raise(|io| {
|
||||
io.timer_init().map(|t| Timer { obj: t })
|
||||
}).map_err(IoError::from_rtio_error)
|
||||
TimerImp::new().map(|t| Timer { inner: t })
|
||||
}
|
||||
|
||||
/// Blocks the current task for the specified duration.
|
||||
@ -106,7 +103,7 @@ impl Timer {
|
||||
// Short-circuit the timer backend for 0 duration
|
||||
let ms = in_ms_u64(duration);
|
||||
if ms == 0 { return }
|
||||
self.obj.sleep(ms);
|
||||
self.inner.sleep(ms);
|
||||
}
|
||||
|
||||
/// Creates a oneshot receiver which will have a notification sent when
|
||||
@ -152,7 +149,7 @@ impl Timer {
|
||||
let (tx, rx) = channel();
|
||||
// Short-circuit the timer backend for 0 duration
|
||||
if in_ms_u64(duration) != 0 {
|
||||
self.obj.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
|
||||
self.inner.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
|
||||
} else {
|
||||
tx.send(());
|
||||
}
|
||||
@ -213,7 +210,7 @@ impl Timer {
|
||||
// not clear what use a 0ms period is anyway...
|
||||
let ms = if ms == 0 { 1 } else { ms };
|
||||
let (tx, rx) = channel();
|
||||
self.obj.period(ms, box TimerCallback { tx: tx });
|
||||
self.inner.period(ms, box TimerCallback { tx: tx });
|
||||
return rx
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ pub mod udp;
|
||||
pub mod pipe;
|
||||
pub mod helper_signal;
|
||||
pub mod process;
|
||||
pub mod timer;
|
||||
|
||||
pub mod addrinfo {
|
||||
pub use sys_common::net::get_host_addresses;
|
||||
|
@ -47,27 +47,30 @@
|
||||
//! Note that all time units in this file are in *milliseconds*.
|
||||
|
||||
use libc;
|
||||
use std::mem;
|
||||
use std::os;
|
||||
use std::ptr;
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::IoResult;
|
||||
use std::sync::atomic;
|
||||
use std::comm;
|
||||
|
||||
use io::c;
|
||||
use platform_imp::fs::FileDesc;
|
||||
use io::helper_thread::Helper;
|
||||
use mem;
|
||||
use os;
|
||||
use ptr;
|
||||
use sync::atomic;
|
||||
use comm;
|
||||
use sys::c;
|
||||
use sys::fs::FileDesc;
|
||||
use sys_common::helper_thread::Helper;
|
||||
use prelude::*;
|
||||
use io::IoResult;
|
||||
|
||||
helper_init!(static HELPER: Helper<Req>)
|
||||
|
||||
pub trait Callback {
|
||||
fn call(&mut self);
|
||||
}
|
||||
|
||||
pub struct Timer {
|
||||
id: uint,
|
||||
inner: Option<Box<Inner>>,
|
||||
}
|
||||
|
||||
pub struct Inner {
|
||||
cb: Option<Box<rtio::Callback + Send>>,
|
||||
cb: Option<Box<Callback + Send>>,
|
||||
interval: u64,
|
||||
repeat: bool,
|
||||
target: u64,
|
||||
@ -190,11 +193,11 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
|
||||
|
||||
// drain the file descriptor
|
||||
let mut buf = [0];
|
||||
assert_eq!(fd.inner_read(buf).ok().unwrap(), 1);
|
||||
assert_eq!(fd.read(buf).ok().unwrap(), 1);
|
||||
}
|
||||
|
||||
-1 if os::errno() == libc::EINTR as int => {}
|
||||
n => panic!("helper thread panicked in select() with error: {} ({})",
|
||||
-1 if os::errno() == libc::EINTR as uint => {}
|
||||
n => panic!("helper thread failed in select() with error: {} ({})",
|
||||
n, os::last_os_error())
|
||||
}
|
||||
}
|
||||
@ -220,7 +223,11 @@ impl Timer {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sleep(ms: u64) {
|
||||
pub fn sleep(&mut self, ms: u64) {
|
||||
let mut inner = self.inner();
|
||||
inner.cb = None; // cancel any previous request
|
||||
self.inner = Some(inner);
|
||||
|
||||
let mut to_sleep = libc::timespec {
|
||||
tv_sec: (ms / 1000) as libc::time_t,
|
||||
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long,
|
||||
@ -232,6 +239,30 @@ impl Timer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn oneshot(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
inner.repeat = false;
|
||||
inner.cb = Some(cb);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
HELPER.send(NewTimer(inner));
|
||||
}
|
||||
|
||||
pub fn period(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
inner.repeat = true;
|
||||
inner.cb = Some(cb);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
HELPER.send(NewTimer(inner));
|
||||
}
|
||||
|
||||
fn inner(&mut self) -> Box<Inner> {
|
||||
match self.inner.take() {
|
||||
Some(i) => i,
|
||||
@ -244,40 +275,6 @@ impl Timer {
|
||||
}
|
||||
}
|
||||
|
||||
impl rtio::RtioTimer for Timer {
|
||||
fn sleep(&mut self, msecs: u64) {
|
||||
let mut inner = self.inner();
|
||||
inner.cb = None; // cancel any previous request
|
||||
self.inner = Some(inner);
|
||||
|
||||
Timer::sleep(msecs);
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64, cb: Box<rtio::Callback + Send>) {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
inner.repeat = false;
|
||||
inner.cb = Some(cb);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
HELPER.send(NewTimer(inner));
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64, cb: Box<rtio::Callback + Send>) {
|
||||
let now = now();
|
||||
let mut inner = self.inner();
|
||||
|
||||
inner.repeat = true;
|
||||
inner.cb = Some(cb);
|
||||
inner.interval = msecs;
|
||||
inner.target = now + msecs;
|
||||
|
||||
HELPER.send(NewTimer(inner));
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Timer {
|
||||
fn drop(&mut self) {
|
||||
self.inner = Some(self.inner());
|
@ -41,6 +41,7 @@ pub mod udp;
|
||||
pub mod pipe;
|
||||
pub mod helper_signal;
|
||||
pub mod process;
|
||||
pub mod timer;
|
||||
|
||||
pub mod addrinfo {
|
||||
pub use sys_common::net::get_host_addresses;
|
||||
|
@ -21,15 +21,21 @@
|
||||
//! the other two implementations of timers with nothing *that* new showing up.
|
||||
|
||||
use libc;
|
||||
use std::ptr;
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::{IoResult, Callback};
|
||||
use std::comm;
|
||||
use ptr;
|
||||
use comm;
|
||||
|
||||
use io::helper_thread::Helper;
|
||||
use sys::c;
|
||||
use sys::fs::FileDesc;
|
||||
use sys_common::helper_thread::Helper;
|
||||
use prelude::*;
|
||||
use io::IoResult;
|
||||
|
||||
helper_init!(static HELPER: Helper<Req>)
|
||||
|
||||
pub trait Callback {
|
||||
fn call(&mut self);
|
||||
}
|
||||
|
||||
pub struct Timer {
|
||||
obj: libc::HANDLE,
|
||||
on_worker: bool,
|
||||
@ -116,12 +122,6 @@ impl Timer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sleep(ms: u64) {
|
||||
use std::rt::rtio::RtioTimer;
|
||||
let mut t = Timer::new().ok().expect("must allocate a timer!");
|
||||
t.sleep(ms);
|
||||
}
|
||||
|
||||
fn remove(&mut self) {
|
||||
if !self.on_worker { return }
|
||||
|
||||
@ -131,10 +131,8 @@ impl Timer {
|
||||
|
||||
self.on_worker = false;
|
||||
}
|
||||
}
|
||||
|
||||
impl rtio::RtioTimer for Timer {
|
||||
fn sleep(&mut self, msecs: u64) {
|
||||
pub fn sleep(&mut self, msecs: u64) {
|
||||
self.remove();
|
||||
|
||||
// there are 10^6 nanoseconds in a millisecond, and the parameter is in
|
||||
@ -148,7 +146,7 @@ impl rtio::RtioTimer for Timer {
|
||||
let _ = unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE) };
|
||||
}
|
||||
|
||||
fn oneshot(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
pub fn oneshot(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
self.remove();
|
||||
|
||||
// see above for the calculation
|
||||
@ -162,7 +160,7 @@ impl rtio::RtioTimer for Timer {
|
||||
self.on_worker = true;
|
||||
}
|
||||
|
||||
fn period(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
pub fn period(&mut self, msecs: u64, cb: Box<Callback + Send>) {
|
||||
self.remove();
|
||||
|
||||
// see above for the calculation
|
Loading…
x
Reference in New Issue
Block a user