Skip to content

Commit c2ae062

Browse files
olsonjefferybrson
authored andcommitted
std: adding tcp::write_future for non-block tcp writes, docs cleanup
1 parent 9b10359 commit c2ae062

File tree

1 file changed

+52
-44
lines changed

1 file changed

+52
-44
lines changed

src/libstd/net_tcp.rs

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import ip = net_ip;
66
import comm::*;
77
import result::*;
88
import str::*;
9+
import future::*;
910

1011
// data
1112
export tcp_socket, tcp_conn_port, tcp_err_data;
1213
// operations on a tcp_socket
13-
export write, read_start, read_stop;
14+
export write, write_future, read_start, read_stop;
1415
// tcp server stuff
1516
export listen_for_conn, accept;
1617
export new_listener, conn_recv, conn_recv_spawn, conn_peek;
@@ -189,7 +190,7 @@ fn connect(input_ip: ip::ip_addr, port: uint)
189190
}
190191

191192
#[doc="
192-
Write binary data to a tcp stream
193+
Write binary data to a tcp stream; Blocks until operatoin completes
193194
194195
# Arguments
195196
@@ -199,55 +200,56 @@ This value must remain valid for the duration of the `write` call
199200
200201
# Returns
201202
202-
A `result` object with a `()` value, in the event of success, or a
203-
`tcp_err_data` value in the event of failure
203+
A `result` object with a `nil` value as the `ok` variant, or a `tcp_err_data`
204+
value as the `err` variant
204205
"]
205-
fn write(sock: tcp_socket, raw_write_data: [[u8]])
206+
fn write(sock: tcp_socket, raw_write_data: [u8])
206207
-> result::result<(), tcp_err_data> unsafe {
207208
let socket_data_ptr = ptr::addr_of(**sock);
208-
let write_req_ptr = ptr::addr_of((*socket_data_ptr).write_req);
209-
let stream_handle_ptr =
210-
(*socket_data_ptr).stream_handle_ptr;
211-
let write_buf_vec = iter::map_to_vec(raw_write_data) {|raw_bytes|
212-
uv::ll::buf_init(vec::unsafe::to_ptr(raw_bytes),
213-
vec::len(raw_bytes))
214-
};
215-
let write_buf_vec_ptr = ptr::addr_of(write_buf_vec);
216-
let result_po = comm::port::<tcp_write_result>();
217-
let write_data = {
218-
result_ch: comm::chan(result_po)
219-
};
220-
let write_data_ptr = ptr::addr_of(write_data);
221-
uv::hl::interact((*socket_data_ptr).hl_loop) {|loop_ptr|
222-
log(debug, #fmt("in interact cb for tcp::write %?", loop_ptr));
223-
alt uv::ll::write(write_req_ptr,
224-
stream_handle_ptr,
225-
write_buf_vec_ptr,
226-
tcp_write_complete_cb) {
227-
0i32 {
228-
log(debug, "uv_write() invoked successfully");
229-
uv::ll::set_data_for_req(write_req_ptr, write_data_ptr);
230-
}
231-
_ {
232-
log(debug, "error invoking uv_write()");
233-
let err_data = uv::ll::get_last_err_data(loop_ptr);
234-
comm::send((*write_data_ptr).result_ch,
235-
tcp_write_error(err_data.to_tcp_err()));
236-
}
237-
}
238-
};
239-
alt comm::recv(result_po) {
240-
tcp_write_success { result::ok(()) }
241-
tcp_write_error(err_data) { result::err(err_data.to_tcp_err()) }
209+
write_common_impl(socket_data_ptr, raw_write_data)
210+
}
211+
212+
#[doc="
213+
Write binary data to tcp stream; Returns a `future::future` value immediately
214+
215+
# Safety
216+
217+
This function can produce unsafe results if the call to `write_future` is
218+
made, the `future::future` value returned is never resolved via
219+
`future::get`, and then the `tcp_socket` passed in to `write_future` leaves
220+
scope and is destructured before the task that runs the libuv write
221+
operation completes.
222+
223+
As such: If using `write_future`, always be sure to resolve the returned
224+
`future` so as to ensure libuv doesn't try to access a released write handle.
225+
Otherwise, use the blocking `tcp::write` function instead.
226+
227+
# Arguments
228+
229+
* sock - a `tcp_socket` to write to
230+
* raw_write_data - a vector of `[u8]` that will be written to the stream.
231+
This value must remain valid for the duration of the `write` call
232+
233+
# Returns
234+
235+
A `future` value that, once the `write` operation completes, resolves to a
236+
`result` object with a `nil` value as the `ok` variant, or a `tcp_err_data`
237+
value as the `err` variant
238+
"]
239+
fn write_future(sock: tcp_socket, raw_write_data: [u8])
240+
-> future::future<result::result<(), tcp_err_data>> unsafe {
241+
let socket_data_ptr = ptr::addr_of(**sock);
242+
future::spawn {||
243+
write_common_impl(socket_data_ptr, raw_write_data)
242244
}
243245
}
244246

245247
#[doc="
246-
Begin reading binary data from an open TCP connection.
248+
Begin reading binary data from an open TCP connection; used with `read_stop`
247249
248250
# Arguments
249251
250-
* sock -- a `tcp_socket` for the connection to read from
252+
* sock -- a `net::tcp::tcp_socket` for the connection to read from
251253
252254
# Returns
253255
@@ -290,7 +292,11 @@ fn read_start(sock: tcp_socket)
290292
}
291293

292294
#[doc="
293-
Stop reading from an open TCP connection.
295+
Stop reading from an open TCP connection; used with `read_start`
296+
297+
# Arguments
298+
299+
* `sock` - a `net::tcp::tcp_socket` that you wish to stop reading on
294300
"]
295301
fn read_stop(sock: tcp_socket) ->
296302
result::result<(), tcp_err_data> unsafe {
@@ -482,11 +488,13 @@ This function behaves similarly to `comm::peek()`
482488
483489
# Arguments
484490
485-
* `server_port` -- a `net::tcp::tcp_conn_port` representing a server connection
491+
* `server_port` -- a `net::tcp::tcp_conn_port` representing a server
492+
connection
486493
487494
# Returns
488495
489-
`true` if there are one-or-more pending connections, `false` if there are none.
496+
`true` if there are one-or-more pending connections, `false` if there are
497+
none.
490498
"]
491499
fn conn_peek(server_port: tcp_conn_port) -> bool {
492500
let new_conn_po = (**server_port).new_conn_po;

0 commit comments

Comments
 (0)