2013-11-05 01:42:05 +01:00
|
|
|
// 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.
|
|
|
|
|
2014-02-26 18:58:41 +01:00
|
|
|
use libc::{c_int, size_t, ssize_t};
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 19:34:51 +02:00
|
|
|
use std::mem;
|
2013-11-08 00:13:06 +01:00
|
|
|
use std::ptr;
|
2013-12-13 02:47:48 +01:00
|
|
|
use std::rt::task::BlockedTask;
|
2013-11-05 01:42:05 +01:00
|
|
|
|
2014-02-11 04:59:35 +01:00
|
|
|
use Loop;
|
2013-11-08 00:13:06 +01:00
|
|
|
use super::{UvError, Buf, slice_to_uv_buf, Request, wait_until_woken_after,
|
2013-12-13 02:47:48 +01:00
|
|
|
ForbidUnwind, wakeup};
|
2013-11-05 01:42:05 +01:00
|
|
|
use uvll;
|
|
|
|
|
|
|
|
// This is a helper structure which is intended to get embedded into other
|
|
|
|
// Watcher structures. This structure will retain a handle to the underlying
|
|
|
|
// uv_stream_t instance, and all I/O operations assume that it's already located
|
|
|
|
// on the appropriate scheduler.
|
|
|
|
pub struct StreamWatcher {
|
2014-06-25 21:47:34 +02:00
|
|
|
pub handle: *mut uvll::uv_stream_t,
|
2013-11-05 01:42:05 +01:00
|
|
|
|
|
|
|
// Cache the last used uv_write_t so we don't have to allocate a new one on
|
|
|
|
// every call to uv_write(). Ideally this would be a stack-allocated
|
|
|
|
// structure, but currently we don't have mappings for all the structures
|
2014-08-02 01:40:21 +02:00
|
|
|
// defined in libuv, so we're forced to malloc this.
|
2014-03-28 18:27:14 +01:00
|
|
|
last_write_req: Option<Request>,
|
2014-04-28 00:45:16 +02:00
|
|
|
|
|
|
|
blocked_writer: Option<BlockedTask>,
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
struct ReadContext {
|
|
|
|
buf: Option<Buf>,
|
2013-11-05 09:27:41 +01:00
|
|
|
result: ssize_t,
|
2013-11-05 01:42:05 +01:00
|
|
|
task: Option<BlockedTask>,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct WriteContext {
|
2013-11-05 09:27:41 +01:00
|
|
|
result: c_int,
|
2014-04-28 00:45:16 +02:00
|
|
|
stream: *mut StreamWatcher,
|
|
|
|
data: Option<Vec<u8>>,
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl StreamWatcher {
|
|
|
|
// Creates a new helper structure which should be then embedded into another
|
|
|
|
// watcher. This provides the generic read/write methods on streams.
|
|
|
|
//
|
|
|
|
// This structure will *not* close the stream when it is dropped. It is up
|
|
|
|
// to the enclosure structure to be sure to call the close method (which
|
|
|
|
// will block the task). Note that this is also required to prevent memory
|
|
|
|
// leaks.
|
|
|
|
//
|
|
|
|
// It should also be noted that the `data` field of the underlying uv handle
|
|
|
|
// will be manipulated on each of the methods called on this watcher.
|
|
|
|
// Wrappers should ensure to always reset the field to an appropriate value
|
|
|
|
// if they rely on the field to perform an action.
|
2014-06-29 18:38:07 +02:00
|
|
|
pub fn new(stream: *mut uvll::uv_stream_t,
|
|
|
|
init: bool) -> StreamWatcher {
|
|
|
|
if init {
|
|
|
|
unsafe { uvll::set_data_for_uv_handle(stream, 0 as *mut int) }
|
|
|
|
}
|
2013-11-05 01:42:05 +01:00
|
|
|
StreamWatcher {
|
|
|
|
handle: stream,
|
|
|
|
last_write_req: None,
|
2014-04-28 00:45:16 +02:00
|
|
|
blocked_writer: None,
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read(&mut self, buf: &mut [u8]) -> Result<uint, UvError> {
|
2013-11-08 00:13:06 +01:00
|
|
|
// This read operation needs to get canceled on an unwind via libuv's
|
|
|
|
// uv_read_stop function
|
|
|
|
let _f = ForbidUnwind::new("stream read");
|
|
|
|
|
2013-11-25 06:47:13 +01:00
|
|
|
let mut rcx = ReadContext {
|
|
|
|
buf: Some(slice_to_uv_buf(buf)),
|
2014-04-25 03:48:21 +02:00
|
|
|
// if the read is canceled, we'll see eof, otherwise this will get
|
|
|
|
// overwritten
|
2014-04-28 00:45:16 +02:00
|
|
|
result: 0,
|
2013-11-25 06:47:13 +01:00
|
|
|
task: None,
|
|
|
|
};
|
|
|
|
// When reading a TTY stream on windows, libuv will invoke alloc_cb
|
|
|
|
// immediately as part of the call to alloc_cb. What this means is that
|
|
|
|
// we must be ready for this to happen (by setting the data in the uv
|
|
|
|
// handle). In theory this otherwise doesn't need to happen until after
|
2014-07-03 03:27:07 +02:00
|
|
|
// the read is successfully started.
|
2014-06-25 21:47:34 +02:00
|
|
|
unsafe { uvll::set_data_for_uv_handle(self.handle, &mut rcx) }
|
2013-11-25 06:47:13 +01:00
|
|
|
|
2013-11-05 01:42:05 +01:00
|
|
|
// Send off the read request, but don't block until we're sure that the
|
|
|
|
// read request is queued.
|
2014-04-25 03:48:21 +02:00
|
|
|
let ret = match unsafe {
|
2013-11-05 01:42:05 +01:00
|
|
|
uvll::uv_read_start(self.handle, alloc_cb, read_cb)
|
|
|
|
} {
|
|
|
|
0 => {
|
2014-02-11 04:59:35 +01:00
|
|
|
let loop_ = unsafe { uvll::get_loop_for_uv_handle(self.handle) };
|
|
|
|
wait_until_woken_after(&mut rcx.task, &Loop::wrap(loop_), || {});
|
2013-11-05 09:27:41 +01:00
|
|
|
match rcx.result {
|
|
|
|
n if n < 0 => Err(UvError(n as c_int)),
|
|
|
|
n => Ok(n as uint),
|
|
|
|
}
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
n => Err(UvError(n))
|
2014-04-25 03:48:21 +02:00
|
|
|
};
|
|
|
|
// Make sure a read cancellation sees that there's no pending read
|
2014-06-25 21:47:34 +02:00
|
|
|
unsafe { uvll::set_data_for_uv_handle(self.handle, 0 as *mut int) }
|
2014-04-25 03:48:21 +02:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-04-28 00:45:16 +02:00
|
|
|
pub fn cancel_read(&mut self, reason: ssize_t) -> Option<BlockedTask> {
|
2014-04-25 03:48:21 +02:00
|
|
|
// When we invoke uv_read_stop, it cancels the read and alloc
|
|
|
|
// callbacks. We need to manually wake up a pending task (if one was
|
2014-04-28 00:45:16 +02:00
|
|
|
// present).
|
2014-04-25 03:48:21 +02:00
|
|
|
assert_eq!(unsafe { uvll::uv_read_stop(self.handle) }, 0);
|
|
|
|
let data = unsafe {
|
|
|
|
let data = uvll::get_data_for_uv_handle(self.handle);
|
2014-04-28 00:45:16 +02:00
|
|
|
if data.is_null() { return None }
|
2014-06-25 21:47:34 +02:00
|
|
|
uvll::set_data_for_uv_handle(self.handle, 0 as *mut int);
|
2014-04-25 03:48:21 +02:00
|
|
|
&mut *(data as *mut ReadContext)
|
|
|
|
};
|
2014-04-28 00:45:16 +02:00
|
|
|
data.result = reason;
|
|
|
|
data.task.take()
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
2014-04-28 00:45:16 +02:00
|
|
|
pub fn write(&mut self, buf: &[u8], may_timeout: bool) -> Result<(), UvError> {
|
2013-11-08 00:13:06 +01:00
|
|
|
// The ownership of the write request is dubious if this function
|
|
|
|
// unwinds. I believe that if the write_cb fails to re-schedule the task
|
|
|
|
// then the write request will be leaked.
|
|
|
|
let _f = ForbidUnwind::new("stream write");
|
|
|
|
|
2013-11-05 01:42:05 +01:00
|
|
|
// Prepare the write request, either using a cached one or allocating a
|
|
|
|
// new one
|
2013-11-08 00:13:06 +01:00
|
|
|
let mut req = match self.last_write_req.take() {
|
|
|
|
Some(req) => req, None => Request::new(uvll::UV_WRITE),
|
|
|
|
};
|
2014-09-15 05:27:36 +02:00
|
|
|
req.set_data(ptr::null_mut::<()>());
|
2013-11-05 01:42:05 +01:00
|
|
|
|
2014-04-28 00:45:16 +02:00
|
|
|
// And here's where timeouts get a little interesting. Currently, libuv
|
|
|
|
// does not support canceling an in-flight write request. Consequently,
|
|
|
|
// when a write timeout expires, there's not much we can do other than
|
|
|
|
// detach the sleeping task from the write request itself. Semantically,
|
|
|
|
// this means that the write request will complete asynchronously, but
|
|
|
|
// the calling task will return error (because the write timed out).
|
|
|
|
//
|
|
|
|
// There is special wording in the documentation of set_write_timeout()
|
|
|
|
// indicating that this is a plausible failure scenario, and this
|
|
|
|
// function is why that wording exists.
|
|
|
|
//
|
|
|
|
// Implementation-wise, we must be careful when passing a buffer down to
|
2014-06-09 06:00:52 +02:00
|
|
|
// libuv. Most of this implementation avoids allocations because of the
|
2014-04-28 00:45:16 +02:00
|
|
|
// blocking guarantee (all stack local variables are valid for the
|
|
|
|
// entire read/write request). If our write request can be timed out,
|
|
|
|
// however, we must heap allocate the data and pass that to the libuv
|
|
|
|
// functions instead. The reason for this is that if we time out and
|
|
|
|
// return, there's no guarantee that `buf` is a valid buffer any more.
|
|
|
|
//
|
|
|
|
// To do this, the write context has an optionally owned vector of
|
|
|
|
// bytes.
|
2014-09-17 21:56:31 +02:00
|
|
|
let data = if may_timeout {Some(buf.to_vec())} else {None};
|
2014-04-28 00:45:16 +02:00
|
|
|
let uv_buf = if may_timeout {
|
2014-08-19 02:52:38 +02:00
|
|
|
slice_to_uv_buf(data.as_ref().unwrap().as_slice())
|
2014-04-28 00:45:16 +02:00
|
|
|
} else {
|
|
|
|
slice_to_uv_buf(buf)
|
|
|
|
};
|
|
|
|
|
2013-11-05 01:42:05 +01:00
|
|
|
// Send off the request, but be careful to not block until we're sure
|
2014-06-09 06:00:52 +02:00
|
|
|
// that the write request is queued. If the request couldn't be queued,
|
2013-11-05 01:42:05 +01:00
|
|
|
// then we should return immediately with an error.
|
|
|
|
match unsafe {
|
2014-04-28 00:45:16 +02:00
|
|
|
uvll::uv_write(req.handle, self.handle, [uv_buf], write_cb)
|
2013-11-05 01:42:05 +01:00
|
|
|
} {
|
|
|
|
0 => {
|
2014-04-28 00:45:16 +02:00
|
|
|
let mut wcx = WriteContext {
|
|
|
|
result: uvll::ECANCELED,
|
|
|
|
stream: self as *mut _,
|
|
|
|
data: data,
|
|
|
|
};
|
2013-11-08 00:13:06 +01:00
|
|
|
req.defuse(); // uv callback now owns this request
|
|
|
|
|
2014-02-11 04:59:35 +01:00
|
|
|
let loop_ = unsafe { uvll::get_loop_for_uv_handle(self.handle) };
|
2014-04-28 00:45:16 +02:00
|
|
|
wait_until_woken_after(&mut self.blocked_writer,
|
|
|
|
&Loop::wrap(loop_), || {
|
2014-06-25 21:47:34 +02:00
|
|
|
req.set_data(&mut wcx);
|
2013-11-21 00:46:49 +01:00
|
|
|
});
|
2014-04-28 00:45:16 +02:00
|
|
|
|
|
|
|
if wcx.result != uvll::ECANCELED {
|
|
|
|
self.last_write_req = Some(Request::wrap(req.handle));
|
|
|
|
return match wcx.result {
|
|
|
|
0 => Ok(()),
|
|
|
|
n => Err(UvError(n)),
|
|
|
|
}
|
2013-11-05 09:27:41 +01:00
|
|
|
}
|
2014-04-28 00:45:16 +02:00
|
|
|
|
|
|
|
// This is the second case where canceling an in-flight write
|
|
|
|
// gets interesting. If we've been canceled (no one reset our
|
|
|
|
// result), then someone still needs to free the request, and
|
|
|
|
// someone still needs to free the allocate buffer.
|
|
|
|
//
|
|
|
|
// To take care of this, we swap out the stack-allocated write
|
|
|
|
// context for a heap-allocated context, transferring ownership
|
|
|
|
// of everything to the write_cb. Libuv guarantees that this
|
|
|
|
// callback will be invoked at some point, and the callback will
|
|
|
|
// be responsible for deallocating these resources.
|
|
|
|
//
|
|
|
|
// Note that we don't cache this write request back in the
|
|
|
|
// stream watcher because we no longer have ownership of it, and
|
|
|
|
// we never will.
|
2014-06-25 21:47:34 +02:00
|
|
|
let mut new_wcx = box WriteContext {
|
2014-04-28 00:45:16 +02:00
|
|
|
result: 0,
|
|
|
|
stream: 0 as *mut StreamWatcher,
|
|
|
|
data: wcx.data.take(),
|
|
|
|
};
|
|
|
|
unsafe {
|
2014-06-25 21:47:34 +02:00
|
|
|
req.set_data(&mut *new_wcx);
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 19:34:51 +02:00
|
|
|
mem::forget(new_wcx);
|
2014-04-28 00:45:16 +02:00
|
|
|
}
|
|
|
|
Err(UvError(wcx.result))
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
n => Err(UvError(n)),
|
|
|
|
}
|
|
|
|
}
|
2014-04-28 00:45:16 +02:00
|
|
|
|
|
|
|
pub fn cancel_write(&mut self) -> Option<BlockedTask> {
|
|
|
|
self.blocked_writer.take()
|
|
|
|
}
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// This allocation callback expects to be invoked once and only once. It will
|
|
|
|
// unwrap the buffer in the ReadContext stored in the stream and return it. This
|
|
|
|
// will fail if it is called more than once.
|
2014-06-25 21:47:34 +02:00
|
|
|
extern fn alloc_cb(stream: *mut uvll::uv_stream_t, _hint: size_t, buf: *mut Buf) {
|
2013-11-08 00:13:06 +01:00
|
|
|
uvdebug!("alloc_cb");
|
2013-11-08 00:26:47 +01:00
|
|
|
unsafe {
|
|
|
|
let rcx: &mut ReadContext =
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 19:34:51 +02:00
|
|
|
mem::transmute(uvll::get_data_for_uv_handle(stream));
|
2013-11-08 00:26:47 +01:00
|
|
|
*buf = rcx.buf.take().expect("stream alloc_cb called more than once");
|
|
|
|
}
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// When a stream has read some data, we will always forcibly stop reading and
|
|
|
|
// return all the data read (even if it didn't fill the whole buffer).
|
2014-06-25 21:47:34 +02:00
|
|
|
extern fn read_cb(handle: *mut uvll::uv_stream_t, nread: ssize_t,
|
|
|
|
_buf: *const Buf) {
|
2013-11-08 00:13:06 +01:00
|
|
|
uvdebug!("read_cb {}", nread);
|
|
|
|
assert!(nread != uvll::ECANCELED as ssize_t);
|
2013-11-05 01:42:05 +01:00
|
|
|
let rcx: &mut ReadContext = unsafe {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 19:34:51 +02:00
|
|
|
mem::transmute(uvll::get_data_for_uv_handle(handle))
|
2013-11-05 01:42:05 +01:00
|
|
|
};
|
|
|
|
// Stop reading so that no read callbacks are
|
|
|
|
// triggered before the user calls `read` again.
|
2014-01-26 09:43:42 +01:00
|
|
|
// FIXME: Is there a performance impact to calling
|
2013-11-05 01:42:05 +01:00
|
|
|
// stop here?
|
|
|
|
unsafe { assert_eq!(uvll::uv_read_stop(handle), 0); }
|
2013-11-05 09:27:41 +01:00
|
|
|
rcx.result = nread;
|
2013-11-05 01:42:05 +01:00
|
|
|
|
2013-12-13 02:47:48 +01:00
|
|
|
wakeup(&mut rcx.task);
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Unlike reading, the WriteContext is stored in the uv_write_t request. Like
|
|
|
|
// reading, however, all this does is wake up the blocked task after squirreling
|
|
|
|
// away the error code as a result.
|
2014-06-25 21:47:34 +02:00
|
|
|
extern fn write_cb(req: *mut uvll::uv_write_t, status: c_int) {
|
2013-11-08 00:13:06 +01:00
|
|
|
let mut req = Request::wrap(req);
|
2013-11-05 01:42:05 +01:00
|
|
|
// Remember to not free the request because it is re-used between writes on
|
|
|
|
// the same stream.
|
2013-11-08 00:13:06 +01:00
|
|
|
let wcx: &mut WriteContext = unsafe { req.get_data() };
|
2013-11-05 09:27:41 +01:00
|
|
|
wcx.result = status;
|
|
|
|
|
2014-04-28 00:45:16 +02:00
|
|
|
// If the stream is present, we haven't timed out, otherwise we acquire
|
|
|
|
// ownership of everything and then deallocate it all at once.
|
|
|
|
if wcx.stream as uint != 0 {
|
|
|
|
req.defuse();
|
|
|
|
let stream: &mut StreamWatcher = unsafe { &mut *wcx.stream };
|
|
|
|
wakeup(&mut stream.blocked_writer);
|
|
|
|
} else {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 19:34:51 +02:00
|
|
|
let _wcx: Box<WriteContext> = unsafe { mem::transmute(wcx) };
|
2014-04-28 00:45:16 +02:00
|
|
|
}
|
2013-11-05 01:42:05 +01:00
|
|
|
}
|