about summary refs log tree commit diff
path: root/src/librustuv/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustuv/lib.rs')
-rw-r--r--src/librustuv/lib.rs536
1 files changed, 0 insertions, 536 deletions
diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs
deleted file mode 100644
index 44cfafe3074..00000000000
--- a/src/librustuv/lib.rs
+++ /dev/null
@@ -1,536 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Bindings to libuv, along with the default implementation of `std::rt::rtio`.
-
-UV types consist of the event loop (Loop), Watchers, Requests and
-Callbacks.
-
-Watchers and Requests encapsulate pointers to uv *handles*, which have
-subtyping relationships with each other.  This subtyping is reflected
-in the bindings with explicit or implicit coercions. For example, an
-upcast from TcpWatcher to StreamWatcher is done with
-`tcp_watcher.as_stream()`. In other cases a callback on a specific
-type of watcher will be passed a watcher of a supertype.
-
-Currently all use of Request types (connect/write requests) are
-encapsulated in the bindings and don't need to be dealt with by the
-caller.
-
-# Safety note
-
-Due to the complex lifecycle of uv handles, as well as compiler bugs,
-this module is not memory safe and requires explicit memory management,
-via `close` and `delete` methods.
-
-*/
-
-#![crate_name = "rustuv"]
-#![experimental]
-#![license = "MIT/ASL2"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
-       html_root_url = "http://doc.rust-lang.org/master/",
-       html_playground_url = "http://play.rust-lang.org/")]
-
-#![feature(macro_rules, unsafe_destructor)]
-#![deny(unused_result, unused_must_use)]
-
-#![reexport_test_harness_main = "test_main"]
-
-#[cfg(test)] extern crate green;
-#[cfg(test)] extern crate debug;
-#[cfg(test)] extern crate "rustuv" as realrustuv;
-extern crate libc;
-extern crate alloc;
-
-use libc::{c_int, c_void};
-use std::fmt;
-use std::mem;
-use std::ptr;
-use std::string;
-use std::rt::local::Local;
-use std::rt::rtio;
-use std::rt::rtio::{IoResult, IoError};
-use std::rt::task::{BlockedTask, Task};
-use std::task;
-
-pub use self::async::AsyncWatcher;
-pub use self::file::{FsRequest, FileWatcher};
-pub use self::idle::IdleWatcher;
-pub use self::net::{TcpWatcher, TcpListener, TcpAcceptor, UdpWatcher};
-pub use self::pipe::{PipeWatcher, PipeListener, PipeAcceptor};
-pub use self::process::Process;
-pub use self::signal::SignalWatcher;
-pub use self::timer::TimerWatcher;
-pub use self::tty::TtyWatcher;
-
-// Run tests with libgreen instead of libnative.
-#[cfg(test)] #[start]
-fn start(argc: int, argv: *const *const u8) -> int {
-    green::start(argc, argv, event_loop, test_main)
-}
-
-mod macros;
-
-mod access;
-mod timeout;
-mod homing;
-mod queue;
-mod rc;
-
-pub mod uvio;
-pub mod uvll;
-
-pub mod file;
-pub mod net;
-pub mod idle;
-pub mod timer;
-pub mod async;
-pub mod addrinfo;
-pub mod process;
-pub mod pipe;
-pub mod tty;
-pub mod signal;
-pub mod stream;
-
-/// Creates a new event loop which is powered by libuv
-///
-/// This function is used in tandem with libgreen's `PoolConfig` type as a value
-/// for the `event_loop_factory` field. Using this function as the event loop
-/// factory will power programs with libuv and enable green threading.
-///
-/// # Example
-///
-/// ```
-/// extern crate rustuv;
-/// extern crate green;
-///
-/// #[start]
-/// fn start(argc: int, argv: *const *const u8) -> int {
-///     green::start(argc, argv, rustuv::event_loop, main)
-/// }
-///
-/// fn main() {
-///     // this code is running inside of a green task powered by libuv
-/// }
-/// ```
-pub fn event_loop() -> Box<rtio::EventLoop + Send> {
-    box uvio::UvEventLoop::new() as Box<rtio::EventLoop + Send>
-}
-
-/// A type that wraps a uv handle
-pub trait UvHandle<T> {
-    fn uv_handle(&self) -> *mut T;
-
-    fn uv_loop(&self) -> Loop {
-        Loop::wrap(unsafe { uvll::get_loop_for_uv_handle(self.uv_handle()) })
-    }
-
-    // FIXME(#8888) dummy self
-    fn alloc(_: Option<Self>, ty: uvll::uv_handle_type) -> *mut T {
-        unsafe {
-            let handle = uvll::malloc_handle(ty);
-            assert!(!handle.is_null());
-            handle as *mut T
-        }
-    }
-
-    unsafe fn from_uv_handle<'a>(h: &'a *mut T) -> &'a mut Self {
-        mem::transmute(uvll::get_data_for_uv_handle(*h))
-    }
-
-    fn install(self: Box<Self>) -> Box<Self> {
-        unsafe {
-            let myptr = mem::transmute::<&Box<Self>, &*mut u8>(&self);
-            uvll::set_data_for_uv_handle(self.uv_handle(), *myptr);
-        }
-        self
-    }
-
-    fn close_async_(&mut self) {
-        // we used malloc to allocate all handles, so we must always have at
-        // least a callback to free all the handles we allocated.
-        extern fn close_cb(handle: *mut uvll::uv_handle_t) {
-            unsafe { uvll::free_handle(handle) }
-        }
-
-        unsafe {
-            uvll::set_data_for_uv_handle(self.uv_handle(), ptr::null_mut::<()>());
-            uvll::uv_close(self.uv_handle() as *mut uvll::uv_handle_t, close_cb)
-        }
-    }
-
-    fn close(&mut self) {
-        let mut slot = None;
-
-        unsafe {
-            uvll::uv_close(self.uv_handle() as *mut uvll::uv_handle_t, close_cb);
-            uvll::set_data_for_uv_handle(self.uv_handle(),
-                                         ptr::null_mut::<()>());
-
-            wait_until_woken_after(&mut slot, &self.uv_loop(), || {
-                uvll::set_data_for_uv_handle(self.uv_handle(), &mut slot);
-            })
-        }
-
-        extern fn close_cb(handle: *mut uvll::uv_handle_t) {
-            unsafe {
-                let data = uvll::get_data_for_uv_handle(handle);
-                uvll::free_handle(handle);
-                if data == ptr::null_mut() { return }
-                let slot: &mut Option<BlockedTask> = mem::transmute(data);
-                wakeup(slot);
-            }
-        }
-    }
-}
-
-pub struct ForbidSwitch {
-    msg: &'static str,
-    io: uint,
-}
-
-impl ForbidSwitch {
-    fn new(s: &'static str) -> ForbidSwitch {
-        ForbidSwitch {
-            msg: s,
-            io: homing::local_id(),
-        }
-    }
-}
-
-impl Drop for ForbidSwitch {
-    fn drop(&mut self) {
-        assert!(self.io == homing::local_id(),
-                "didn't want a scheduler switch: {}",
-                self.msg);
-    }
-}
-
-pub struct ForbidUnwind {
-    msg: &'static str,
-    failing_before: bool,
-}
-
-impl ForbidUnwind {
-    fn new(s: &'static str) -> ForbidUnwind {
-        ForbidUnwind {
-            msg: s, failing_before: task::failing(),
-        }
-    }
-}
-
-impl Drop for ForbidUnwind {
-    fn drop(&mut self) {
-        assert!(self.failing_before == task::failing(),
-                "didn't want an unwind during: {}", self.msg);
-    }
-}
-
-fn wait_until_woken_after(slot: *mut Option<BlockedTask>,
-                          loop_: &Loop,
-                          f: ||) {
-    let _f = ForbidUnwind::new("wait_until_woken_after");
-    unsafe {
-        assert!((*slot).is_none());
-        let task: Box<Task> = Local::take();
-        loop_.modify_blockers(1);
-        task.deschedule(1, |task| {
-            *slot = Some(task);
-            f();
-            Ok(())
-        });
-        loop_.modify_blockers(-1);
-    }
-}
-
-fn wakeup(slot: &mut Option<BlockedTask>) {
-    assert!(slot.is_some());
-    let _ = slot.take().unwrap().wake().map(|t| t.reawaken());
-}
-
-pub struct Request {
-    pub handle: *mut uvll::uv_req_t,
-    defused: bool,
-}
-
-impl Request {
-    pub fn new(ty: uvll::uv_req_type) -> Request {
-        unsafe {
-            let handle = uvll::malloc_req(ty);
-            uvll::set_data_for_req(handle, ptr::null_mut::<()>());
-            Request::wrap(handle)
-        }
-    }
-
-    pub fn wrap(handle: *mut uvll::uv_req_t) -> Request {
-        Request { handle: handle, defused: false }
-    }
-
-    pub fn set_data<T>(&self, t: *mut T) {
-        unsafe { uvll::set_data_for_req(self.handle, t) }
-    }
-
-    pub unsafe fn get_data<T>(&self) -> &'static mut T {
-        let data = uvll::get_data_for_req(self.handle);
-        assert!(data != ptr::null_mut());
-        mem::transmute(data)
-    }
-
-    // This function should be used when the request handle has been given to an
-    // underlying uv function, and the uv function has succeeded. This means
-    // that uv will at some point invoke the callback, and in the meantime we
-    // can't deallocate the handle because libuv could be using it.
-    //
-    // This is still a problem in blocking situations due to linked failure. In
-    // the connection callback the handle should be re-wrapped with the `wrap`
-    // function to ensure its destruction.
-    pub fn defuse(&mut self) {
-        self.defused = true;
-    }
-}
-
-impl Drop for Request {
-    fn drop(&mut self) {
-        if !self.defused {
-            unsafe { uvll::free_req(self.handle) }
-        }
-    }
-}
-
-/// FIXME: Loop(*handle) is buggy with destructors. Normal structs
-/// with dtors may not be destructured, but tuple structs can,
-/// but the results are not correct.
-pub struct Loop {
-    handle: *mut uvll::uv_loop_t
-}
-
-impl Loop {
-    pub fn new() -> Loop {
-        let handle = unsafe { uvll::loop_new() };
-        assert!(handle.is_not_null());
-        unsafe { uvll::set_data_for_uv_loop(handle, 0 as *mut c_void) }
-        Loop::wrap(handle)
-    }
-
-    pub fn wrap(handle: *mut uvll::uv_loop_t) -> Loop { Loop { handle: handle } }
-
-    pub fn run(&mut self) {
-        assert_eq!(unsafe { uvll::uv_run(self.handle, uvll::RUN_DEFAULT) }, 0);
-    }
-
-    pub fn close(&mut self) {
-        unsafe { uvll::uv_loop_delete(self.handle) };
-    }
-
-    // The 'data' field of the uv_loop_t is used to count the number of tasks
-    // that are currently blocked waiting for I/O to complete.
-    fn modify_blockers(&self, amt: uint) {
-        unsafe {
-            let cur = uvll::get_data_for_uv_loop(self.handle) as uint;
-            uvll::set_data_for_uv_loop(self.handle, (cur + amt) as *mut c_void)
-        }
-    }
-
-    fn get_blockers(&self) -> uint {
-        unsafe { uvll::get_data_for_uv_loop(self.handle) as uint }
-    }
-}
-
-// FIXME: Need to define the error constants like EOF so they can be
-// compared to the UvError type
-
-pub struct UvError(c_int);
-
-impl UvError {
-    pub fn name(&self) -> String {
-        unsafe {
-            let inner = match self { &UvError(a) => a };
-            let name_str = uvll::uv_err_name(inner);
-            assert!(name_str.is_not_null());
-            string::raw::from_buf(name_str as *const u8)
-        }
-    }
-
-    pub fn desc(&self) -> String {
-        unsafe {
-            let inner = match self { &UvError(a) => a };
-            let desc_str = uvll::uv_strerror(inner);
-            assert!(desc_str.is_not_null());
-            string::raw::from_buf(desc_str as *const u8)
-        }
-    }
-
-    pub fn is_eof(&self) -> bool {
-        let UvError(handle) = *self;
-        handle == uvll::EOF
-    }
-}
-
-impl fmt::Show for UvError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}: {}", self.name(), self.desc())
-    }
-}
-
-#[test]
-fn error_smoke_test() {
-    let err: UvError = UvError(uvll::EOF);
-    assert_eq!(err.to_string(), "EOF: end of file".to_string());
-}
-
-#[cfg(unix)]
-pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
-    let UvError(errcode) = uverr;
-    IoError {
-        code: if errcode == uvll::EOF {libc::EOF as uint} else {-errcode as uint},
-        extra: 0,
-        detail: Some(uverr.desc()),
-    }
-}
-
-#[cfg(windows)]
-pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
-    let UvError(errcode) = uverr;
-    IoError {
-        code: match errcode {
-            uvll::EOF => libc::EOF,
-            uvll::EACCES => libc::ERROR_ACCESS_DENIED,
-            uvll::ECONNREFUSED => libc::WSAECONNREFUSED,
-            uvll::ECONNRESET => libc::WSAECONNRESET,
-            uvll::ENOTCONN => libc::WSAENOTCONN,
-            uvll::ENOENT => libc::ERROR_FILE_NOT_FOUND,
-            uvll::EPIPE => libc::ERROR_NO_DATA,
-            uvll::ECONNABORTED => libc::WSAECONNABORTED,
-            uvll::EADDRNOTAVAIL => libc::WSAEADDRNOTAVAIL,
-            uvll::ECANCELED => libc::ERROR_OPERATION_ABORTED,
-            uvll::EADDRINUSE => libc::WSAEADDRINUSE,
-            uvll::EPERM => libc::ERROR_ACCESS_DENIED,
-            err => {
-                uvdebug!("uverr.code {}", err as int);
-                // FIXME: Need to map remaining uv error types
-                -1
-            }
-        } as uint,
-        extra: 0,
-        detail: Some(uverr.desc()),
-    }
-}
-
-/// Given a uv error code, convert a callback status to a UvError
-pub fn status_to_maybe_uv_error(status: c_int) -> Option<UvError> {
-    if status >= 0 {
-        None
-    } else {
-        Some(UvError(status))
-    }
-}
-
-pub fn status_to_io_result(status: c_int) -> IoResult<()> {
-    if status >= 0 {Ok(())} else {Err(uv_error_to_io_error(UvError(status)))}
-}
-
-/// The uv buffer type
-pub type Buf = uvll::uv_buf_t;
-
-pub fn empty_buf() -> Buf {
-    uvll::uv_buf_t {
-        base: ptr::null_mut(),
-        len: 0,
-    }
-}
-
-/// Borrow a slice to a Buf
-pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
-    let data = v.as_ptr();
-    uvll::uv_buf_t { base: data as *mut u8, len: v.len() as uvll::uv_buf_len_t }
-}
-
-// This function is full of lies!
-#[cfg(test)]
-fn local_loop() -> &'static mut uvio::UvIoFactory {
-    use std::raw::TraitObject;
-    unsafe {
-        mem::transmute({
-            let mut task = Local::borrow(None::<Task>);
-            let mut io = task.local_io().unwrap();
-            let obj: TraitObject =
-                mem::transmute(io.get());
-            obj.data
-        })
-    }
-}
-
-#[cfg(test)]
-fn next_test_ip4() -> std::rt::rtio::SocketAddr {
-    use std::io;
-    use std::rt::rtio;
-
-    let io::net::ip::SocketAddr { ip, port } = io::test::next_test_ip4();
-    let ip = match ip {
-        io::net::ip::Ipv4Addr(a, b, c, d) => rtio::Ipv4Addr(a, b, c, d),
-        _ => unreachable!(),
-    };
-    rtio::SocketAddr { ip: ip, port: port }
-}
-
-#[cfg(test)]
-fn next_test_ip6() -> std::rt::rtio::SocketAddr {
-    use std::io;
-    use std::rt::rtio;
-
-    let io::net::ip::SocketAddr { ip, port } = io::test::next_test_ip6();
-    let ip = match ip {
-        io::net::ip::Ipv6Addr(a, b, c, d, e, f, g, h) =>
-            rtio::Ipv6Addr(a, b, c, d, e, f, g, h),
-        _ => unreachable!(),
-    };
-    rtio::SocketAddr { ip: ip, port: port }
-}
-
-#[cfg(test)]
-mod test {
-    use std::mem::transmute;
-    use std::rt::thread::Thread;
-
-    use super::{slice_to_uv_buf, Loop};
-
-    #[test]
-    fn test_slice_to_uv_buf() {
-        let slice = [0, .. 20];
-        let buf = slice_to_uv_buf(slice);
-
-        assert_eq!(buf.len, 20);
-
-        unsafe {
-            let base = transmute::<*mut u8, *mut u8>(buf.base);
-            (*base) = 1;
-            (*base.offset(1)) = 2;
-        }
-
-        assert!(slice[0] == 1);
-        assert!(slice[1] == 2);
-    }
-
-
-    #[test]
-    fn loop_smoke_test() {
-        Thread::start(proc() {
-            let mut loop_ = Loop::new();
-            loop_.run();
-            loop_.close();
-        }).join();
-    }
-}