Skip to content

Commit 4e26e59

Browse files
olsonjefferybrson
authored andcommitted
---
yaml --- r: 11518 b: refs/heads/master c: b68eb50 h: refs/heads/master v: v3
1 parent f24ca2a commit 4e26e59

File tree

3 files changed

+280
-75
lines changed

3 files changed

+280
-75
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 974c23cbeb4c0183723bac89aa50bf58e0bf7f6c
2+
refs/heads/master: b68eb507da6a2621a74676fc9a4ca76b37561ec8
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/libstd/uvtmp.rs

Lines changed: 188 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
// Some temporary libuv hacks for servo
22

33
// UV2
4+
5+
// these are processed solely in the
6+
// process_operation() crust fn below
47
enum uv_operation {
5-
op_async_init([u8])
8+
op_async_init([u8]),
9+
op_close(uv_handle, *ctypes::void)
610
}
711

8-
type uv_async = {
9-
id: [u8],
10-
loop: uv_loop
11-
};
12+
enum uv_handle {
13+
uv_async([u8], uv_loop)
14+
}
1215

1316
enum uv_msg {
1417
// requests from library users
1518
msg_run(comm::chan<bool>),
1619
msg_run_in_bg(),
17-
msg_loop_delete(),
18-
msg_async_init(fn~(uv_async), fn~(uv_async)),
20+
msg_async_init(fn~(uv_handle), fn~(uv_handle)),
1921
msg_async_send([u8]),
22+
msg_close(uv_handle, fn~()),
2023

2124
// dispatches from libuv
2225
uv_async_init([u8], *ctypes::void),
23-
uv_async_send([u8])
26+
uv_async_send([u8]),
27+
uv_close([u8]),
28+
uv_end()
2429
}
2530

2631
type uv_loop_data = {
@@ -65,7 +70,10 @@ native mod rustrt {
6570
loop: *ctypes::void,
6671
data: *uv_loop_data);
6772
fn rust_uvtmp_uv_bind_op_cb(loop: *ctypes::void, cb: *u8) -> *ctypes::void;
73+
fn rust_uvtmp_uv_stop_op_cb(handle: *ctypes::void);
6874
fn rust_uvtmp_uv_run(loop_handle: *ctypes::void);
75+
fn rust_uvtmp_uv_close(handle: *ctypes::void, cb: *u8);
76+
fn rust_uvtmp_uv_close_async(handle: *ctypes::void);
6977
fn rust_uvtmp_uv_async_send(handle: *ctypes::void);
7078
fn rust_uvtmp_uv_async_init(
7179
loop_handle: *ctypes::void,
@@ -74,7 +82,8 @@ native mod rustrt {
7482
}
7583

7684
mod uv {
77-
export loop_new, run, run_in_bg, async_init, async_send;
85+
export loop_new, run, close, run_in_bg, async_init, async_send,
86+
timer_init;
7887

7988
// public functions
8089
fn loop_new() -> uv_loop unsafe {
@@ -129,10 +138,14 @@ mod uv {
129138
// all state goes here
130139
let handles: map::map<[u8], *ctypes::void> =
131140
map::new_bytes_hash();
132-
let async_cbs: map::map<[u8], fn~(uv_async)> =
141+
let id_to_handle: map::map<[u8], uv_handle> =
142+
map::new_bytes_hash();
143+
let async_cbs: map::map<[u8], fn~(uv_handle)> =
133144
map::new_bytes_hash();
134145
let async_init_after_cbs: map::map<[u8],
135-
fn~(uv_async)> =
146+
fn~(uv_handle)> =
147+
map::new_bytes_hash();
148+
let close_callbacks: map::map<[u8], fn~()> =
136149
map::new_bytes_hash();
137150

138151
// the main loop that this task blocks on.
@@ -152,7 +165,9 @@ mod uv {
152165
rustrt::rust_uvtmp_uv_run(loop_handle);
153166
// when we're done, msg the
154167
// end chan
168+
rustrt::rust_uvtmp_uv_stop_op_cb(op_handle);
155169
comm::send(end_chan, true);
170+
comm::send(rust_loop_chan, uv_end);
156171
};
157172
}
158173

@@ -163,6 +178,34 @@ mod uv {
163178
};
164179
}
165180

181+
msg_close(handle, cb) {
182+
let id = get_id_from_handle(handle);
183+
close_callbacks.insert(id, cb);
184+
let handle_ptr = handles.get(id);
185+
let op = op_close(handle, handle_ptr);
186+
187+
pass_to_libuv(op_handle, operation_chan, op);
188+
}
189+
uv_close(id) {
190+
handles.remove(id);
191+
let handle = id_to_handle.get(id);
192+
id_to_handle.remove(id);
193+
alt handle {
194+
uv_async(id, _) {
195+
async_cbs.remove(id);
196+
}
197+
_ {
198+
fail "unknown form of uv_handle encountered "
199+
+ "in uv_close handler";
200+
}
201+
}
202+
let cb = close_callbacks.get(id);
203+
close_callbacks.remove(id);
204+
task::spawn {||
205+
cb();
206+
};
207+
}
208+
166209
msg_async_init(callback, after_cb) {
167210
// create a new async handle
168211
// with the id as the handle's
@@ -172,9 +215,7 @@ mod uv {
172215
async_cbs.insert(id, callback);
173216
async_init_after_cbs.insert(id, after_cb);
174217
let op = op_async_init(id);
175-
comm::send(operation_chan, op);
176-
rustrt::rust_uvtmp_uv_async_send(op_handle);
177-
io::println("MSG_ASYNC_INIT");
218+
pass_to_libuv(op_handle, operation_chan, op);
178219
}
179220
uv_async_init(id, async_handle) {
180221
// libuv created a handle, which is
@@ -184,22 +225,25 @@ mod uv {
184225
handles.insert(id, async_handle);
185226
let after_cb = async_init_after_cbs.get(id);
186227
async_init_after_cbs.remove(id);
228+
let async = uv_async(id, rust_loop_chan);
229+
id_to_handle.insert(id, copy(async));
187230
task::spawn {||
188-
let async: uv_async = {
189-
id: id,
190-
loop: rust_loop_chan
191-
};
192231
after_cb(async);
193232
};
194233
}
195234

196235
msg_async_send(id) {
197236
let async_handle = handles.get(id);
198-
rustrt::rust_uvtmp_uv_async_send(async_handle);
237+
do_send(async_handle);
199238
}
200239
uv_async_send(id) {
201240
let async_cb = async_cbs.get(id);
202-
async_cb({id: id, loop: rust_loop_chan});
241+
task::spawn {||
242+
async_cb(uv_async(id, rust_loop_chan));
243+
};
244+
}
245+
uv_end() {
246+
keep_going = false;
203247
}
204248

205249
_ { fail "unknown form of uv_msg received"; }
@@ -222,42 +266,91 @@ mod uv {
222266

223267
fn async_init (
224268
loop: uv_loop,
225-
async_cb: fn~(uv_async),
226-
after_cb: fn~(uv_async)) {
269+
async_cb: fn~(uv_handle),
270+
after_cb: fn~(uv_handle)) {
227271
let msg = msg_async_init(async_cb, after_cb);
228272
comm::send(loop, msg);
229273
}
230274

231-
fn async_send(async: uv_async) {
232-
comm::send(async.loop, msg_async_send(async.id));
275+
fn async_send(async: uv_handle) {
276+
alt async {
277+
uv_async(id, loop) {
278+
comm::send(loop, msg_async_send(id));
279+
}
280+
_ {
281+
fail "attempting to call async_send() with a" +
282+
" uv_async uv_handle";
283+
}
284+
}
285+
}
286+
287+
fn close(h: uv_handle, cb: fn~()) {
288+
let loop_chan = get_loop_chan_from_handle(h);
289+
comm::send(loop_chan, msg_close(h, cb));
290+
}
291+
292+
fn timer_init(loop: uv_loop, after_cb: fn~(uv_handle)) {
293+
let msg = msg_timer_init(after_cb);
294+
comm::send(loop, msg);
233295
}
234296

235297
// internal functions
298+
fn pass_to_libuv(
299+
op_handle: *ctypes::void,
300+
operation_chan: comm::chan<uv_operation>,
301+
op: uv_operation) unsafe {
302+
comm::send(operation_chan, copy(op));
303+
do_send(op_handle);
304+
}
305+
fn do_send(h: *ctypes::void) {
306+
rustrt::rust_uvtmp_uv_async_send(h);
307+
}
236308
fn gen_handle_id() -> [u8] {
237309
ret rand::mk_rng().gen_bytes(16u);
238310
}
239311
fn get_handle_id_from(buf: *u8) -> [u8] unsafe {
240312
ret vec::unsafe::from_buf(buf, 16u);
241313
}
242314

243-
fn get_loop_chan_from(data: *uv_loop_data)
244-
-> comm::chan<uv_msg> unsafe {
315+
fn get_loop_chan_from_data(data: *uv_loop_data)
316+
-> uv_loop unsafe {
245317
ret (*data).rust_loop_chan;
246318
}
247319

320+
fn get_loop_chan_from_handle(handle: uv_handle)
321+
-> uv_loop {
322+
alt handle {
323+
uv_async(id,loop) {
324+
ret loop;
325+
}
326+
_ {
327+
fail "unknown form of uv_handle for get_loop_chan_from "
328+
+ " handle";
329+
}
330+
}
331+
}
332+
333+
fn get_id_from_handle(handle: uv_handle) -> [u8] {
334+
alt handle {
335+
uv_async(id,loop) {
336+
ret id;
337+
}
338+
_ {
339+
fail "unknown form of uv_handle for get_id_from handle";
340+
}
341+
}
342+
}
343+
248344
// crust
249345
crust fn process_operation(
250346
loop: *ctypes::void,
251347
data: *uv_loop_data) unsafe {
252-
io::println("IN PROCESS_OPERATION");
253348
let op_port = (*data).operation_port;
254-
let loop_chan = get_loop_chan_from(data);
349+
let loop_chan = get_loop_chan_from_data(data);
255350
let op_pending = comm::peek(op_port);
256351
while(op_pending) {
257-
io::println("OPERATION PENDING!");
258352
alt comm::recv(op_port) {
259353
op_async_init(id) {
260-
io::println("OP_ASYNC_INIT");
261354
let id_ptr = vec::unsafe::to_ptr(id);
262355
let async_handle = rustrt::rust_uvtmp_uv_async_init(
263356
loop,
@@ -267,21 +360,61 @@ mod uv {
267360
id,
268361
async_handle));
269362
}
363+
op_close(handle, handle_ptr) {
364+
handle_op_close(handle, handle_ptr);
365+
}
270366

271367
_ { fail "unknown form of uv_operation received"; }
272368
}
273369
op_pending = comm::peek(op_port);
274370
}
275-
io::println("NO MORE OPERATIONS PENDING!");
371+
}
372+
373+
fn handle_op_close(handle: uv_handle, handle_ptr: *ctypes::void) {
374+
// it's just like im doing C
375+
alt handle {
376+
uv_async(id, loop) {
377+
let cb = process_close_async;
378+
rustrt::rust_uvtmp_uv_close(
379+
handle_ptr, cb);
380+
}
381+
_ {
382+
fail "unknown form of uv_handle encountered " +
383+
"in process_operation/op_close";
384+
}
385+
}
276386
}
277387

278388
crust fn process_async_send(id_buf: *u8, data: *uv_loop_data)
279389
unsafe {
280390
let handle_id = get_handle_id_from(id_buf);
281-
let loop_chan = get_loop_chan_from(data);
391+
let loop_chan = get_loop_chan_from_data(data);
282392
comm::send(loop_chan, uv_async_send(handle_id));
283393
}
284394

395+
fn process_close_common(id: [u8], data: *uv_loop_data)
396+
unsafe {
397+
// notify the rust loop that their handle is closed, then
398+
// the caller will invoke a per-handle-type c++ func to
399+
// free allocated memory
400+
let loop_chan = get_loop_chan_from_data(data);
401+
comm::send(loop_chan, uv_close(id));
402+
}
403+
404+
crust fn process_close_async(
405+
id_buf: *u8,
406+
handle_ptr: *ctypes::void,
407+
data: *uv_loop_data)
408+
unsafe {
409+
let id = get_handle_id_from(id_buf);
410+
rustrt::rust_uvtmp_uv_close_async(handle_ptr);
411+
// at this point, the handle and its data has been
412+
// released. notify the rust loop to remove the
413+
// handle and its data and call the user-supplied
414+
// close cb
415+
process_close_common(id, data);
416+
}
417+
285418

286419
}
287420

@@ -295,14 +428,31 @@ fn test_uvtmp_uv_new_loop_no_handles() {
295428
#[test]
296429
fn test_uvtmp_uv_simple_async() {
297430
let test_loop = uv::loop_new();
298-
let cb: fn~(uv_async) = fn~(h: uv_async) {
299-
io::println("HELLO FROM ASYNC CALLBACK!");
300-
};
301-
uv::async_init(test_loop, cb) {|new_async|
302-
io::println("NEW_ASYNC CREATED!");
431+
let exit_port = comm::port::<bool>();
432+
let exit_chan = comm::chan::<bool>(exit_port);
433+
uv::async_init(test_loop, {|new_async|
434+
uv::close(new_async) {||
435+
comm::send(exit_chan, true);
436+
};
437+
}, {|new_async|
303438
uv::async_send(new_async);
304-
};
439+
});
440+
uv::run(test_loop);
441+
assert comm::recv(exit_port);
442+
}
443+
444+
#[test]
445+
fn test_uvtmp_uv_timer() {
446+
let test_loop = uv::loop_new();
447+
let exit_port = comm::port::<bool>();
448+
let exit_chan = comm::chan::<bool>(exit_port);
449+
uv::timer(test_loop, {|new_timer|
450+
uv::timer_start(new_async) {||
451+
comm::send(exit_chan, true);
452+
};
453+
});
305454
uv::run(test_loop);
455+
assert comm::recv(exit_port);
306456
}
307457

308458
// END OF UV2

0 commit comments

Comments
 (0)