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:
Aaron Turon 2014-10-16 18:57:11 -07:00
parent 0f98e75b69
commit b8f1193bb1
6 changed files with 71 additions and 94 deletions

View File

@ -29,19 +29,6 @@ use std::os;
use std::rt::rtio::{mod, IoResult, IoError}; use std::rt::rtio::{mod, IoResult, IoError};
use std::num; 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)] #[cfg(windows)]
#[path = "tty_windows.rs"] #[path = "tty_windows.rs"]
mod tty; mod tty;
@ -112,10 +99,6 @@ impl IoFactory {
} }
impl rtio::IoFactory for 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)] #[cfg(unix)]
fn tty_open(&mut self, fd: c_int, _readable: bool) fn tty_open(&mut self, fd: c_int, _readable: bool)
-> IoResult<Box<rtio::RtioTTY + Send>> { -> IoResult<Box<rtio::RtioTTY + Send>> {

View File

@ -21,10 +21,9 @@ and create receivers which will receive notifications after a period of time.
use comm::{Receiver, Sender, channel}; use comm::{Receiver, Sender, channel};
use time::Duration; use time::Duration;
use io::{IoResult, IoError}; use io::IoResult;
use kinds::Send; use sys::timer::Callback;
use boxed::Box; use sys::timer::Timer as TimerImp;
use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
/// A synchronous timer object /// A synchronous timer object
/// ///
@ -69,7 +68,7 @@ use rt::rtio::{IoFactory, LocalIo, RtioTimer, Callback};
/// # } /// # }
/// ``` /// ```
pub struct Timer { pub struct Timer {
obj: Box<RtioTimer + Send>, inner: TimerImp,
} }
struct TimerCallback { tx: Sender<()> } struct TimerCallback { tx: Sender<()> }
@ -90,9 +89,7 @@ impl Timer {
/// for a number of milliseconds, or to possibly create channels which will /// for a number of milliseconds, or to possibly create channels which will
/// get notified after an amount of time has passed. /// get notified after an amount of time has passed.
pub fn new() -> IoResult<Timer> { pub fn new() -> IoResult<Timer> {
LocalIo::maybe_raise(|io| { TimerImp::new().map(|t| Timer { inner: t })
io.timer_init().map(|t| Timer { obj: t })
}).map_err(IoError::from_rtio_error)
} }
/// Blocks the current task for the specified duration. /// Blocks the current task for the specified duration.
@ -106,7 +103,7 @@ impl Timer {
// Short-circuit the timer backend for 0 duration // Short-circuit the timer backend for 0 duration
let ms = in_ms_u64(duration); let ms = in_ms_u64(duration);
if ms == 0 { return } if ms == 0 { return }
self.obj.sleep(ms); self.inner.sleep(ms);
} }
/// Creates a oneshot receiver which will have a notification sent when /// Creates a oneshot receiver which will have a notification sent when
@ -152,7 +149,7 @@ impl Timer {
let (tx, rx) = channel(); let (tx, rx) = channel();
// Short-circuit the timer backend for 0 duration // Short-circuit the timer backend for 0 duration
if in_ms_u64(duration) != 0 { 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 { } else {
tx.send(()); tx.send(());
} }
@ -213,7 +210,7 @@ impl Timer {
// not clear what use a 0ms period is anyway... // not clear what use a 0ms period is anyway...
let ms = if ms == 0 { 1 } else { ms }; let ms = if ms == 0 { 1 } else { ms };
let (tx, rx) = channel(); let (tx, rx) = channel();
self.obj.period(ms, box TimerCallback { tx: tx }); self.inner.period(ms, box TimerCallback { tx: tx });
return rx return rx
} }
} }

View File

@ -34,6 +34,7 @@ pub mod udp;
pub mod pipe; pub mod pipe;
pub mod helper_signal; pub mod helper_signal;
pub mod process; pub mod process;
pub mod timer;
pub mod addrinfo { pub mod addrinfo {
pub use sys_common::net::get_host_addresses; pub use sys_common::net::get_host_addresses;

View File

@ -47,27 +47,30 @@
//! Note that all time units in this file are in *milliseconds*. //! Note that all time units in this file are in *milliseconds*.
use libc; use libc;
use std::mem; use mem;
use std::os; use os;
use std::ptr; use ptr;
use std::rt::rtio; use sync::atomic;
use std::rt::rtio::IoResult; use comm;
use std::sync::atomic; use sys::c;
use std::comm; use sys::fs::FileDesc;
use sys_common::helper_thread::Helper;
use io::c; use prelude::*;
use platform_imp::fs::FileDesc; use io::IoResult;
use io::helper_thread::Helper;
helper_init!(static HELPER: Helper<Req>) helper_init!(static HELPER: Helper<Req>)
pub trait Callback {
fn call(&mut self);
}
pub struct Timer { pub struct Timer {
id: uint, id: uint,
inner: Option<Box<Inner>>, inner: Option<Box<Inner>>,
} }
pub struct Inner { pub struct Inner {
cb: Option<Box<rtio::Callback + Send>>, cb: Option<Box<Callback + Send>>,
interval: u64, interval: u64,
repeat: bool, repeat: bool,
target: u64, target: u64,
@ -190,11 +193,11 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) {
// drain the file descriptor // drain the file descriptor
let mut buf = [0]; 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 => {} -1 if os::errno() == libc::EINTR as uint => {}
n => panic!("helper thread panicked in select() with error: {} ({})", n => panic!("helper thread failed in select() with error: {} ({})",
n, os::last_os_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 { let mut to_sleep = libc::timespec {
tv_sec: (ms / 1000) as libc::time_t, tv_sec: (ms / 1000) as libc::time_t,
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long, 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> { fn inner(&mut self) -> Box<Inner> {
match self.inner.take() { match self.inner.take() {
Some(i) => i, 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 { impl Drop for Timer {
fn drop(&mut self) { fn drop(&mut self) {
self.inner = Some(self.inner()); self.inner = Some(self.inner());

View File

@ -41,6 +41,7 @@ pub mod udp;
pub mod pipe; pub mod pipe;
pub mod helper_signal; pub mod helper_signal;
pub mod process; pub mod process;
pub mod timer;
pub mod addrinfo { pub mod addrinfo {
pub use sys_common::net::get_host_addresses; pub use sys_common::net::get_host_addresses;

View File

@ -21,15 +21,21 @@
//! the other two implementations of timers with nothing *that* new showing up. //! the other two implementations of timers with nothing *that* new showing up.
use libc; use libc;
use std::ptr; use ptr;
use std::rt::rtio; use comm;
use std::rt::rtio::{IoResult, Callback};
use std::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>) helper_init!(static HELPER: Helper<Req>)
pub trait Callback {
fn call(&mut self);
}
pub struct Timer { pub struct Timer {
obj: libc::HANDLE, obj: libc::HANDLE,
on_worker: bool, 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) { fn remove(&mut self) {
if !self.on_worker { return } if !self.on_worker { return }
@ -131,10 +131,8 @@ impl Timer {
self.on_worker = false; self.on_worker = false;
} }
}
impl rtio::RtioTimer for Timer { pub fn sleep(&mut self, msecs: u64) {
fn sleep(&mut self, msecs: u64) {
self.remove(); self.remove();
// there are 10^6 nanoseconds in a millisecond, and the parameter is in // 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) }; 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(); self.remove();
// see above for the calculation // see above for the calculation
@ -162,7 +160,7 @@ impl rtio::RtioTimer for Timer {
self.on_worker = true; 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(); self.remove();
// see above for the calculation // see above for the calculation