From b8f1193bb1bb66610f479cd78e3dc5526e93058d Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Thu, 16 Oct 2014 18:57:11 -0700 Subject: [PATCH] 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. --- src/libnative/io/mod.rs | 17 ---- src/libstd/io/timer.rs | 19 ++-- src/libstd/sys/unix/mod.rs | 1 + .../sys/unix/timer.rs} | 97 +++++++++---------- src/libstd/sys/windows/mod.rs | 1 + .../sys/windows/timer.rs} | 30 +++--- 6 files changed, 71 insertions(+), 94 deletions(-) rename src/{libnative/io/timer_unix.rs => libstd/sys/unix/timer.rs} (92%) rename src/{libnative/io/timer_windows.rs => libstd/sys/windows/timer.rs} (93%) diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 29370dee88b..5d6d23f5f03 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -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> { - timer::Timer::new().map(|t| box t as Box) - } #[cfg(unix)] fn tty_open(&mut self, fd: c_int, _readable: bool) -> IoResult> { diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index d16199da77f..ec588f13478 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -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, + 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 { - 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 } } diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index b404dc7fdbd..03a4e56f00d 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -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; diff --git a/src/libnative/io/timer_unix.rs b/src/libstd/sys/unix/timer.rs similarity index 92% rename from src/libnative/io/timer_unix.rs rename to src/libstd/sys/unix/timer.rs index c26e2e76cee..a1e6ac3db7e 100644 --- a/src/libnative/io/timer_unix.rs +++ b/src/libstd/sys/unix/timer.rs @@ -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) +pub trait Callback { + fn call(&mut self); +} + pub struct Timer { id: uint, inner: Option>, } pub struct Inner { - cb: Option>, + cb: Option>, interval: u64, repeat: bool, target: u64, @@ -190,11 +193,11 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { // 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) { + 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) { + 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 { 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) { - 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) { - 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()); diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index f50244701e4..0dc06de33e0 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -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; diff --git a/src/libnative/io/timer_windows.rs b/src/libstd/sys/windows/timer.rs similarity index 93% rename from src/libnative/io/timer_windows.rs rename to src/libstd/sys/windows/timer.rs index c17c541fc01..f507be2a985 100644 --- a/src/libnative/io/timer_windows.rs +++ b/src/libstd/sys/windows/timer.rs @@ -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) +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) { + pub fn oneshot(&mut self, msecs: u64, cb: Box) { 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) { + pub fn period(&mut self, msecs: u64, cb: Box) { self.remove(); // see above for the calculation