From 921d99108cd452f92569a0cafc8d11b36b38dfc0 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 19 Jul 2013 16:02:38 -0700 Subject: [PATCH 1/5] std: add RtioTimer and UvTimer impl atop rt::uv --- src/libstd/rt/rtio.rs | 6 ++++ src/libstd/rt/uv/uvio.rs | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs index 10eba85188ef0..aa8b9dc3a944d 100644 --- a/src/libstd/rt/rtio.rs +++ b/src/libstd/rt/rtio.rs @@ -23,6 +23,7 @@ pub type IoFactoryObject = uvio::UvIoFactory; pub type RtioTcpStreamObject = uvio::UvTcpStream; pub type RtioTcpListenerObject = uvio::UvTcpListener; pub type RtioUdpSocketObject = uvio::UvUdpSocket; +pub type RtioTimerObject = uvio::UvTimer; pub trait EventLoop { fn run(&mut self); @@ -46,6 +47,7 @@ pub trait IoFactory { fn tcp_connect(&mut self, addr: IpAddr) -> Result<~RtioTcpStreamObject, IoError>; fn tcp_bind(&mut self, addr: IpAddr) -> Result<~RtioTcpListenerObject, IoError>; fn udp_bind(&mut self, addr: IpAddr) -> Result<~RtioUdpSocketObject, IoError>; + fn timer_init(&mut self) -> Result<~RtioTimerObject, IoError>; } pub trait RtioTcpListener : RtioSocket { @@ -84,3 +86,7 @@ pub trait RtioUdpSocket : RtioSocket { fn hear_broadcasts(&mut self); fn ignore_broadcasts(&mut self); } + +pub trait RtioTimer { + fn sleep(&self, msecs: u64); +} diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 9b96c8717346d..4ecfa46328422 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -280,6 +280,10 @@ impl IoFactory for UvIoFactory { } } } + + fn timer_init(&mut self) -> Result<~RtioTimerObject, IoError> { + Ok(~UvTimer(TimerWatcher::new(self.uv_loop()))) + } } // FIXME #6090: Prefer newtype structs but Drop doesn't work @@ -562,6 +566,48 @@ impl RtioUdpSocket for UvUdpSocket { fn ignore_broadcasts(&mut self) { fail!(); } } +pub struct UvTimer(timer::TimerWatcher); + +impl UvTimer { + fn new(w: timer::TimerWatcher) -> UvTimer { + UvTimer(w) + } +} + +impl Drop for UvTimer { + fn drop(&self) { + rtdebug!("closing UvTimer"); + let scheduler = Local::take::(); + do scheduler.deschedule_running_task_and_then |_, task| { + let task_cell = Cell::new(task); + do self.close { + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + } +} + +impl RtioTimer for UvTimer { + fn sleep(&self, msecs: u64) { + let scheduler = Local::take::(); + assert!(scheduler.in_task_context()); + do scheduler.deschedule_running_task_and_then |sched, task| { + rtdebug!("sleep: entered scheduler context"); + assert!(!sched.in_task_context()); + let task_cell = Cell::new(task); + let mut watcher = **self; + do watcher.start(msecs, 0) |_, status| { + assert!(status.is_none()); + let scheduler = Local::take::(); + scheduler.resume_task_immediately(task_cell.take()); + } + } + let mut w = **self; + w.stop(); + } +} + #[test] fn test_simple_io_no_connect() { do run_in_newsched_task { @@ -832,3 +878,20 @@ fn test_udp_many_read() { } } } + +fn test_timer_sleep_simple_impl() { + unsafe { + let io = Local::unsafe_borrow::(); + let timer = (*io).timer_init(); + match timer { + Ok(t) => t.sleep(1), + Err(_) => assert!(false) + } + } +} +#[test] +fn test_timer_sleep_simple() { + do run_in_newsched_task { + test_timer_sleep_simple_impl(); + } +} From 5da29e3278b639540679e88fc7dd008435066e9a Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 19 Jul 2013 16:03:02 -0700 Subject: [PATCH 2/5] std: add rt::io::Timer --- src/libstd/rt/io/mod.rs | 4 +++ src/libstd/rt/io/timer.rs | 63 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/libstd/rt/io/timer.rs diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs index 0ec51a3aa941e..e261b3a3c579d 100644 --- a/src/libstd/rt/io/mod.rs +++ b/src/libstd/rt/io/mod.rs @@ -252,6 +252,7 @@ pub use self::stdio::print; pub use self::stdio::println; pub use self::file::FileStream; +pub use self::timer::Timer; pub use self::net::ip::IpAddr; pub use self::net::tcp::TcpListener; pub use self::net::tcp::TcpStream; @@ -296,6 +297,9 @@ mod extensions; /// Non-I/O things needed by the I/O module mod support; +/// Basic Timer +mod timer; + /// Thread-blocking implementations pub mod native { /// Posix file I/O diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs new file mode 100644 index 0000000000000..1a5fc66f183f4 --- /dev/null +++ b/src/libstd/rt/io/timer.rs @@ -0,0 +1,63 @@ +// copyright 2013 the rust project developers. see the copyright +// file at the top-level directory of this distribution and at +// http://rust-lang.org/copyright. +// +// licensed under the apache license, version 2.0 or the mit license +// , at your +// option. this file may not be copied, modified, or distributed +// except according to those terms. +use option::{Option, Some, None}; +use result::{Ok, Err}; +use rt::io::{io_error}; +use rt::rtio::{IoFactory, IoFactoryObject, + RtioTimer, RtioTimerObject}; +use rt::local::Local; + +pub struct Timer(~RtioTimerObject); + +impl Timer { + fn new(i: ~RtioTimerObject) -> Timer { + Timer(i) + } + + pub fn init() -> Option { + let timer = unsafe { + rtdebug!("Timer::init: borrowing io to init timer"); + let io = Local::unsafe_borrow::(); + rtdebug!("about to init timer"); + (*io).timer_init() + }; + match timer { + Ok(t) => Some(Timer::new(t)), + Err(ioerr) => { + rtdebug!("Timer::init: failed to init: %?", ioerr); + io_error::cond.raise(ioerr); + None + } + } + } +} + +impl RtioTimer for Timer { + fn sleep(&self, msecs: u64) { + (**self).sleep(msecs); + } +} + +#[cfg(test)] +mod test { + use super::*; + use rt::test::*; + use option::{Some, None}; + #[test] + fn test_io_timer_sleep_simple() { + do run_in_newsched_task { + let timer = Timer::init(); + match timer { + Some(t) => t.sleep(1), + None => assert!(false) + } + } + } +} \ No newline at end of file From 155470fc9cd8e1cdfd0f6ecc558f865f54c1ef29 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 19 Jul 2013 16:22:13 -0700 Subject: [PATCH 3/5] std: minor timer cleanup based on feedback --- src/libstd/rt/io/mod.rs | 2 +- src/libstd/rt/io/timer.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs index e261b3a3c579d..838c2d86c9fa2 100644 --- a/src/libstd/rt/io/mod.rs +++ b/src/libstd/rt/io/mod.rs @@ -298,7 +298,7 @@ mod extensions; mod support; /// Basic Timer -mod timer; +pub mod timer; /// Thread-blocking implementations pub mod native { diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs index 1a5fc66f183f4..f80a91e988c22 100644 --- a/src/libstd/rt/io/timer.rs +++ b/src/libstd/rt/io/timer.rs @@ -17,11 +17,11 @@ use rt::local::Local; pub struct Timer(~RtioTimerObject); impl Timer { - fn new(i: ~RtioTimerObject) -> Timer { + fn new_on_rt(i: ~RtioTimerObject) -> Timer { Timer(i) } - pub fn init() -> Option { + pub fn new() -> Option { let timer = unsafe { rtdebug!("Timer::init: borrowing io to init timer"); let io = Local::unsafe_borrow::(); @@ -29,7 +29,7 @@ impl Timer { (*io).timer_init() }; match timer { - Ok(t) => Some(Timer::new(t)), + Ok(t) => Some(Timer::new_on_rt(t)), Err(ioerr) => { rtdebug!("Timer::init: failed to init: %?", ioerr); io_error::cond.raise(ioerr); @@ -53,7 +53,7 @@ mod test { #[test] fn test_io_timer_sleep_simple() { do run_in_newsched_task { - let timer = Timer::init(); + let timer = Timer::new(); match timer { Some(t) => t.sleep(1), None => assert!(false) From 73ab6c60f37263871a5e69f3eeaad72f0d804a02 Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Fri, 19 Jul 2013 16:24:07 -0700 Subject: [PATCH 4/5] std: make check appeasement --- src/libstd/rt/io/timer.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs index f80a91e988c22..c7820ebf6238b 100644 --- a/src/libstd/rt/io/timer.rs +++ b/src/libstd/rt/io/timer.rs @@ -1,12 +1,13 @@ -// copyright 2013 the rust project developers. see the copyright +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at -// http://rust-lang.org/copyright. +// http://rust-lang.org/COPYRIGHT. // -// licensed under the apache license, version 2.0 or the mit license -// , at your -// option. this file may not be copied, modified, or distributed +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed // except according to those terms. + use option::{Option, Some, None}; use result::{Ok, Err}; use rt::io::{io_error}; From 3169bb70d8bef4fea776916f900bf9e407e6469c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 22 Jul 2013 15:28:32 -0700 Subject: [PATCH 5/5] std: fix for blocked task resume --- src/libstd/rt/uv/uvio.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index 4ecfa46328422..9c386b4bed11d 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -582,7 +582,7 @@ impl Drop for UvTimer { let task_cell = Cell::new(task); do self.close { let scheduler = Local::take::(); - scheduler.resume_task_immediately(task_cell.take()); + scheduler.resume_blocked_task_immediately(task_cell.take()); } } } @@ -600,7 +600,7 @@ impl RtioTimer for UvTimer { do watcher.start(msecs, 0) |_, status| { assert!(status.is_none()); let scheduler = Local::take::(); - scheduler.resume_task_immediately(task_cell.take()); + scheduler.resume_blocked_task_immediately(task_cell.take()); } } let mut w = **self;