about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/rtio.rs6
-rw-r--r--src/libstd/rt/uv/uvio.rs63
2 files changed, 69 insertions, 0 deletions
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
index 10eba85188e..aa8b9dc3a94 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 9b96c871734..4ecfa463284 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::<Scheduler>();
+        do scheduler.deschedule_running_task_and_then |_, task| {
+            let task_cell = Cell::new(task);
+            do self.close {
+                let scheduler = Local::take::<Scheduler>();
+                scheduler.resume_task_immediately(task_cell.take());
+            }
+        }
+    }
+}
+
+impl RtioTimer for UvTimer {
+    fn sleep(&self, msecs: u64) {
+        let scheduler = Local::take::<Scheduler>();
+        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>();
+                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::<IoFactoryObject>();
+        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();
+    }
+}