]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/uv/async.rs
Upgrade libuv to the current master (again)
[rust.git] / src / libstd / rt / uv / async.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use libc::{c_int, c_void};
12 use option::Some;
13 use rt::uv::uvll;
14 use rt::uv::uvll::UV_ASYNC;
15 use rt::uv::{Watcher, Loop, NativeHandle, AsyncCallback, NullCallback};
16 use rt::uv::WatcherInterop;
17 use rt::uv::status_to_maybe_uv_error;
18
19 pub struct AsyncWatcher(*uvll::uv_async_t);
20 impl Watcher for AsyncWatcher { }
21
22 impl AsyncWatcher {
23     pub fn new(loop_: &mut Loop, cb: AsyncCallback) -> AsyncWatcher {
24         unsafe {
25             let handle = uvll::malloc_handle(UV_ASYNC);
26             assert!(handle.is_not_null());
27             let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
28             watcher.install_watcher_data();
29             let data = watcher.get_watcher_data();
30             data.async_cb = Some(cb);
31             assert_eq!(0, uvll::async_init(loop_.native_handle(), handle, async_cb));
32             return watcher;
33         }
34
35         extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
36             let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
37             let status = status_to_maybe_uv_error(status);
38             let data = watcher.get_watcher_data();
39             let cb = data.async_cb.get_ref();
40             (*cb)(watcher, status);
41         }
42     }
43
44     pub fn send(&mut self) {
45         unsafe {
46             let handle = self.native_handle();
47             uvll::async_send(handle);
48         }
49     }
50
51     pub fn close(self, cb: NullCallback) {
52         let mut this = self;
53         let data = this.get_watcher_data();
54         assert!(data.close_cb.is_none());
55         data.close_cb = Some(cb);
56
57         unsafe {
58             uvll::close(self.native_handle(), close_cb);
59         }
60
61         extern fn close_cb(handle: *uvll::uv_stream_t) {
62             let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
63             {
64                 let data = watcher.get_watcher_data();
65                 data.close_cb.take_unwrap()();
66             }
67             watcher.drop_watcher_data();
68             unsafe { uvll::free_handle(handle as *c_void); }
69         }
70     }
71 }
72
73 impl NativeHandle<*uvll::uv_async_t> for AsyncWatcher {
74     fn from_native_handle(handle: *uvll::uv_async_t) -> AsyncWatcher {
75         AsyncWatcher(handle)
76     }
77     fn native_handle(&self) -> *uvll::uv_async_t {
78         match self { &AsyncWatcher(ptr) => ptr }
79     }
80 }
81
82 #[cfg(test)]
83 mod test {
84
85     use super::*;
86     use rt::uv::Loop;
87     use unstable::run_in_bare_thread;
88     use rt::thread::Thread;
89     use cell::Cell;
90
91     #[test]
92     fn smoke_test() {
93         do run_in_bare_thread {
94             let mut loop_ = Loop::new();
95             let watcher = AsyncWatcher::new(&mut loop_, |w, _| w.close(||()) );
96             let watcher_cell = Cell::new(watcher);
97             let thread = do Thread::start {
98                 let mut watcher = watcher_cell.take();
99                 watcher.send();
100             };
101             loop_.run();
102             loop_.close();
103             thread.join();
104         }
105     }
106 }