6
6
// process_operation() crust fn below
7
7
enum uv_operation {
8
8
op_async_init( [ u8 ] ) ,
9
- op_close( uv_handle , * ctypes:: void )
9
+ op_close( uv_handle , * ctypes:: void ) ,
10
+ op_timer_init( [ u8 ] ) ,
11
+ op_timer_start( [ u8 ] , * ctypes:: void , u32 , u32 ) ,
12
+ op_timer_stop( [ u8 ] , * ctypes:: void , fn ~( uv_handle ) )
10
13
}
11
14
12
15
enum uv_handle {
13
- uv_async( [ u8 ] , uv_loop )
16
+ uv_async( [ u8 ] , uv_loop ) ,
17
+ uv_timer( [ u8 ] , uv_loop )
14
18
}
15
19
16
20
enum uv_msg {
@@ -20,11 +24,17 @@ enum uv_msg {
20
24
msg_async_init( fn ~( uv_handle ) , fn ~( uv_handle ) ) ,
21
25
msg_async_send( [ u8 ] ) ,
22
26
msg_close( uv_handle , fn ~( ) ) ,
27
+ msg_timer_init( fn ~( uv_handle ) ) ,
28
+ msg_timer_start( [ u8 ] , u32 , u32 , fn ~( uv_handle ) ) ,
29
+ msg_timer_stop( [ u8 ] , fn ~( uv_handle ) ) ,
23
30
24
31
// dispatches from libuv
25
32
uv_async_init( [ u8 ] , * ctypes:: void ) ,
26
33
uv_async_send( [ u8 ] ) ,
27
34
uv_close( [ u8 ] ) ,
35
+ uv_timer_init( [ u8 ] , * ctypes:: void ) ,
36
+ uv_timer_call( [ u8 ] ) ,
37
+ uv_timer_stop( [ u8 ] , fn ~( uv_handle ) ) ,
28
38
uv_end( )
29
39
}
30
40
@@ -74,16 +84,26 @@ native mod rustrt {
74
84
fn rust_uvtmp_uv_run ( loop_handle : * ctypes:: void ) ;
75
85
fn rust_uvtmp_uv_close ( handle : * ctypes:: void , cb : * u8 ) ;
76
86
fn rust_uvtmp_uv_close_async ( handle : * ctypes:: void ) ;
87
+ fn rust_uvtmp_uv_close_timer ( handle : * ctypes:: void ) ;
77
88
fn rust_uvtmp_uv_async_send ( handle : * ctypes:: void ) ;
78
89
fn rust_uvtmp_uv_async_init (
79
90
loop_handle : * ctypes:: void ,
80
91
cb : * u8 ,
81
92
id : * u8 ) -> * ctypes:: void ;
93
+ fn rust_uvtmp_uv_timer_init (
94
+ loop_handle : * ctypes:: void ,
95
+ cb : * u8 ,
96
+ id : * u8 ) -> * ctypes:: void ;
97
+ fn rust_uvtmp_uv_timer_start (
98
+ timer_handle : * ctypes:: void ,
99
+ timeout : ctypes:: c_uint ,
100
+ repeat : ctypes:: c_uint ) ;
101
+ fn rust_uvtmp_uv_timer_stop ( handle : * ctypes:: void ) ;
82
102
}
83
103
84
104
mod uv {
85
105
export loop_new, run, close, run_in_bg, async_init, async_send,
86
- timer_init;
106
+ timer_init, timer_start , timer_stop ;
87
107
88
108
// public functions
89
109
fn loop_new ( ) -> uv_loop unsafe {
@@ -92,9 +112,7 @@ mod uv {
92
112
let ret_recv_chan: comm:: chan < uv_loop > =
93
113
comm:: chan ( ret_recv_port) ;
94
114
95
- let num_threads = 4 u; // would be cool to tie this to
96
- // the number of logical procs
97
- task:: spawn_sched ( num_threads) { ||
115
+ task:: spawn_sched ( task:: manual_threads ( 4 u) ) { ||
98
116
// our beloved uv_loop_t ptr
99
117
let loop_handle = rustrt::
100
118
rust_uvtmp_uv_loop_new ( ) ;
@@ -140,13 +158,15 @@ mod uv {
140
158
map:: new_bytes_hash ( ) ;
141
159
let id_to_handle: map:: map < [ u8 ] , uv_handle > =
142
160
map:: new_bytes_hash ( ) ;
143
- let async_cbs: map:: map < [ u8 ] , fn ~( uv_handle ) > =
144
- map:: new_bytes_hash ( ) ;
145
- let async_init_after_cbs: map:: map < [ u8 ] ,
146
- fn ~( uv_handle ) > =
161
+ let after_cbs: map:: map < [ u8 ] , fn ~( uv_handle ) > =
147
162
map:: new_bytes_hash ( ) ;
148
163
let close_callbacks: map:: map < [ u8 ] , fn ~( ) > =
149
164
map:: new_bytes_hash ( ) ;
165
+
166
+ let async_cbs: map:: map < [ u8 ] , fn ~( uv_handle ) > =
167
+ map:: new_bytes_hash ( ) ;
168
+ let timer_cbs: map:: map < [ u8 ] , fn ~( uv_handle ) > =
169
+ map:: new_bytes_hash ( ) ;
150
170
151
171
// the main loop that this task blocks on.
152
172
// should have the same lifetime as the C libuv
@@ -160,7 +180,7 @@ mod uv {
160
180
// the operation handle to have the
161
181
// loop process any pending operations
162
182
// once its up and running
163
- task:: spawn_sched ( 1 u ) { ||
183
+ task:: spawn_sched ( task :: manual_threads ( 1 u ) ) { ||
164
184
// this call blocks
165
185
rustrt:: rust_uvtmp_uv_run ( loop_handle) ;
166
186
// when we're done, msg the
@@ -172,7 +192,7 @@ mod uv {
172
192
}
173
193
174
194
msg_run_in_bg {
175
- task : : spawn_sched ( 1 u ) { ||
195
+ task : : spawn_sched ( task :: manual_threads ( 1 u ) ) { ||
176
196
// this call blocks
177
197
rustrt:: rust_uvtmp_uv_run ( loop_handle) ;
178
198
} ;
@@ -194,6 +214,9 @@ mod uv {
194
214
uv_async( id, _) {
195
215
async_cbs. remove ( id) ;
196
216
}
217
+ uv_timer ( id, _) {
218
+ timer_cbs. remove ( id) ;
219
+ }
197
220
_ {
198
221
fail "unknown form of uv_handle encountered "
199
222
+ "in uv_close handler" ;
@@ -213,7 +236,7 @@ mod uv {
213
236
// invocation on msg_async_send
214
237
let id = gen_handle_id ( ) ;
215
238
async_cbs. insert ( id, callback) ;
216
- async_init_after_cbs . insert ( id, after_cb) ;
239
+ after_cbs . insert ( id, after_cb) ;
217
240
let op = op_async_init ( id) ;
218
241
pass_to_libuv ( op_handle, operation_chan, op) ;
219
242
}
@@ -223,8 +246,8 @@ mod uv {
223
246
// then invoke the supplied callback
224
247
// for after completion
225
248
handles. insert ( id, async_handle) ;
226
- let after_cb = async_init_after_cbs . get ( id) ;
227
- async_init_after_cbs . remove ( id) ;
249
+ let after_cb = after_cbs . get ( id) ;
250
+ after_cbs . remove ( id) ;
228
251
let async = uv_async ( id, rust_loop_chan) ;
229
252
id_to_handle. insert ( id, copy ( async ) ) ;
230
253
task:: spawn { ||
@@ -242,6 +265,50 @@ mod uv {
242
265
async_cb ( uv_async ( id, rust_loop_chan) ) ;
243
266
} ;
244
267
}
268
+
269
+ msg_timer_init ( after_cb) {
270
+ let id = gen_handle_id ( ) ;
271
+ after_cbs. insert ( id, after_cb) ;
272
+ let op = op_timer_init ( id) ;
273
+ pass_to_libuv ( op_handle, operation_chan, op) ;
274
+ }
275
+ uv_timer_init ( id, handle) {
276
+ handles. insert ( id, handle) ;
277
+ let after_cb = after_cbs. get ( id) ;
278
+ after_cbs. remove ( id) ;
279
+ let new_timer = uv_timer ( id, rust_loop_chan) ;
280
+ id_to_handle. insert ( id, copy ( new_timer) ) ;
281
+ task:: spawn { ||
282
+ after_cb ( new_timer) ;
283
+ } ;
284
+ }
285
+
286
+ uv_timer_call ( id) {
287
+ let cb = timer_cbs. get ( id) ;
288
+ let the_timer = id_to_handle. get ( id) ;
289
+ task:: spawn { ||
290
+ cb ( the_timer) ;
291
+ } ;
292
+ }
293
+
294
+ msg_timer_start ( id, timeout, repeat, timer_call_cb) {
295
+ timer_cbs. insert ( id, timer_call_cb) ;
296
+ let handle = handles. get ( id) ;
297
+ let op = op_timer_start ( id, handle, timeout,
298
+ repeat) ;
299
+ pass_to_libuv ( op_handle, operation_chan, op) ;
300
+ }
301
+
302
+ msg_timer_stop ( id, after_cb) {
303
+ let handle = handles. get ( id) ;
304
+ let op = op_timer_stop ( id, handle, after_cb) ;
305
+ pass_to_libuv ( op_handle, operation_chan, op) ;
306
+ }
307
+ uv_timer_stop ( id, after_cb) {
308
+ let the_timer = id_to_handle. get ( id) ;
309
+ after_cb ( the_timer) ;
310
+ }
311
+
245
312
uv_end ( ) {
246
313
keep_going = false ;
247
314
}
@@ -294,6 +361,33 @@ mod uv {
294
361
comm:: send ( loop , msg) ;
295
362
}
296
363
364
+ fn timer_start ( the_timer : uv_handle , timeout : u32 , repeat : u32 ,
365
+ timer_cb : fn ~( uv_handle ) ) {
366
+ alt the_timer {
367
+ uv_timer( id, loop_chan) {
368
+ let msg = msg_timer_start ( id, timeout, repeat, timer_cb) ;
369
+ comm:: send ( loop_chan, msg) ;
370
+ }
371
+ _ {
372
+ fail "can only pass a uv_timer form of uv_handle to " +
373
+ " uv::timer_start()" ;
374
+ }
375
+ }
376
+ }
377
+
378
+ fn timer_stop ( the_timer : uv_handle , after_cb : fn ~( uv_handle ) ) {
379
+ alt the_timer {
380
+ uv_timer( id, loop_chan) {
381
+ let msg = msg_timer_stop ( id, after_cb) ;
382
+ comm:: send ( loop_chan, msg) ;
383
+ }
384
+ _ {
385
+ fail "only uv_timer form is allowed in calls to " +
386
+ " uv::timer_stop()" ;
387
+ }
388
+ }
389
+ }
390
+
297
391
// internal functions
298
392
fn pass_to_libuv (
299
393
op_handle : * ctypes:: void ,
@@ -320,7 +414,7 @@ mod uv {
320
414
fn get_loop_chan_from_handle ( handle : uv_handle )
321
415
-> uv_loop {
322
416
alt handle {
323
- uv_async( id, loop ) {
417
+ uv_async( id, loop ) | uv_timer ( id , loop ) {
324
418
ret loop;
325
419
}
326
420
_ {
@@ -332,7 +426,7 @@ mod uv {
332
426
333
427
fn get_id_from_handle ( handle: uv_handle) -> [ u8] {
334
428
alt handle {
335
- uv_async( id, loop ) {
429
+ uv_async( id, loop ) | uv_timer ( id , loop ) {
336
430
ret id;
337
431
}
338
432
_ {
@@ -363,6 +457,24 @@ mod uv {
363
457
op_close ( handle, handle_ptr) {
364
458
handle_op_close ( handle, handle_ptr) ;
365
459
}
460
+ op_timer_init ( id) {
461
+ let id_ptr = vec:: unsafe:: to_ptr ( id) ;
462
+ let timer_handle = rustrt:: rust_uvtmp_uv_timer_init (
463
+ loop ,
464
+ process_timer_call,
465
+ id_ptr) ;
466
+ comm:: send ( loop_chan, uv_timer_init (
467
+ id,
468
+ timer_handle) ) ;
469
+ }
470
+ op_timer_start ( id, handle, timeout, repeat) {
471
+ rustrt:: rust_uvtmp_uv_timer_start ( handle, timeout,
472
+ repeat) ;
473
+ }
474
+ op_timer_stop ( id, handle, after_cb) {
475
+ rustrt:: rust_uvtmp_uv_timer_stop ( handle) ;
476
+ comm:: send ( loop_chan, uv_timer_stop ( id, after_cb) ) ;
477
+ }
366
478
367
479
_ { fail "unknown form of uv_operation received" ; }
368
480
}
@@ -378,6 +490,11 @@ mod uv {
378
490
rustrt:: rust_uvtmp_uv_close (
379
491
handle_ptr, cb) ;
380
492
}
493
+ uv_timer( id, loop ) {
494
+ let cb = process_close_timer;
495
+ rustrt:: rust_uvtmp_uv_close (
496
+ handle_ptr, cb) ;
497
+ }
381
498
_ {
382
499
fail "unknown form of uv_handle encountered " +
383
500
"in process_operation/op_close" ;
@@ -386,12 +503,19 @@ mod uv {
386
503
}
387
504
388
505
crust fn process_async_send ( id_buf : * u8 , data : * uv_loop_data )
389
- unsafe {
506
+ unsafe {
390
507
let handle_id = get_handle_id_from ( id_buf) ;
391
508
let loop_chan = get_loop_chan_from_data ( data) ;
392
509
comm:: send ( loop_chan, uv_async_send ( handle_id) ) ;
393
510
}
394
511
512
+ crust fn process_timer_call ( id_buf : * u8 , data : * uv_loop_data )
513
+ unsafe {
514
+ let handle_id = get_handle_id_from ( id_buf) ;
515
+ let loop_chan = get_loop_chan_from_data ( data) ;
516
+ comm:: send ( loop_chan, uv_timer_call ( handle_id) ) ;
517
+ }
518
+
395
519
fn process_close_common ( id : [ u8 ] , data : * uv_loop_data )
396
520
unsafe {
397
521
// notify the rust loop that their handle is closed, then
@@ -414,6 +538,16 @@ mod uv {
414
538
// close cb
415
539
process_close_common ( id, data) ;
416
540
}
541
+
542
+ crust fn process_close_timer (
543
+ id_buf : * u8 ,
544
+ handle_ptr : * ctypes:: void ,
545
+ data : * uv_loop_data )
546
+ unsafe {
547
+ let id = get_handle_id_from ( id_buf) ;
548
+ rustrt:: rust_uvtmp_uv_close_timer ( handle_ptr) ;
549
+ process_close_common ( id, data) ;
550
+ }
417
551
418
552
419
553
}
@@ -446,11 +580,15 @@ fn test_uvtmp_uv_timer() {
446
580
let test_loop = uv:: loop_new ( ) ;
447
581
let exit_port = comm:: port :: < bool > ( ) ;
448
582
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 ) ;
583
+ uv:: timer_init ( test_loop) { |new_timer|
584
+ uv:: timer_start ( new_timer, 1u32 , 0u32 ) { |started_timer|
585
+ uv:: timer_stop ( started_timer) { |stopped_timer|
586
+ uv:: close ( stopped_timer) { ||
587
+ comm:: send ( exit_chan, true ) ;
588
+ } ;
589
+ } ;
452
590
} ;
453
- } ) ;
591
+ } ;
454
592
uv:: run ( test_loop) ;
455
593
assert comm:: recv ( exit_port) ;
456
594
}
0 commit comments