@@ -6,11 +6,12 @@ import ip = net_ip;
6
6
import comm:: * ;
7
7
import result:: * ;
8
8
import str:: * ;
9
+ import future:: * ;
9
10
10
11
// data
11
12
export tcp_socket, tcp_conn_port, tcp_err_data;
12
13
// operations on a tcp_socket
13
- export write, read_start, read_stop;
14
+ export write, write_future , read_start, read_stop;
14
15
// tcp server stuff
15
16
export listen_for_conn, accept;
16
17
export new_listener, conn_recv, conn_recv_spawn, conn_peek;
@@ -189,7 +190,7 @@ fn connect(input_ip: ip::ip_addr, port: uint)
189
190
}
190
191
191
192
#[ doc="
192
- Write binary data to a tcp stream
193
+ Write binary data to a tcp stream; Blocks until operatoin completes
193
194
194
195
# Arguments
195
196
@@ -199,55 +200,56 @@ This value must remain valid for the duration of the `write` call
199
200
200
201
# Returns
201
202
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
204
205
" ]
205
- fn write ( sock : tcp_socket , raw_write_data : [ [ u8 ] ] )
206
+ fn write ( sock : tcp_socket , raw_write_data : [ u8 ] )
206
207
-> result:: result < ( ) , tcp_err_data > unsafe {
207
208
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)
242
244
}
243
245
}
244
246
245
247
#[ 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`
247
249
248
250
# Arguments
249
251
250
- * sock -- a `tcp_socket` for the connection to read from
252
+ * sock -- a `net::tcp:: tcp_socket` for the connection to read from
251
253
252
254
# Returns
253
255
@@ -290,7 +292,11 @@ fn read_start(sock: tcp_socket)
290
292
}
291
293
292
294
#[ 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
294
300
" ]
295
301
fn read_stop ( sock : tcp_socket ) ->
296
302
result:: result < ( ) , tcp_err_data > unsafe {
@@ -482,11 +488,13 @@ This function behaves similarly to `comm::peek()`
482
488
483
489
# Arguments
484
490
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
486
493
487
494
# Returns
488
495
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.
490
498
" ]
491
499
fn conn_peek ( server_port : tcp_conn_port ) -> bool {
492
500
let new_conn_po = ( * * server_port) . new_conn_po ;
0 commit comments