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::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>> {

View File

@ -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
}
}

View File

@ -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;

View File

@ -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());

View File

@ -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;

View File

@ -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