@@ -15,7 +15,7 @@ use cell::Cell;
15
15
16
16
use super :: work_queue:: WorkQueue ;
17
17
use super :: stack:: { StackPool , StackSegment } ;
18
- use super :: rtio:: { EventLoop , EventLoopObject } ;
18
+ use super :: rtio:: { EventLoop , EventLoopObject , RemoteCallbackObject } ;
19
19
use super :: context:: Context ;
20
20
use super :: task:: Task ;
21
21
use rt:: local_ptr;
@@ -41,16 +41,19 @@ pub struct Scheduler {
41
41
priv cleanup_job : Option < CleanupJob >
42
42
}
43
43
44
- // XXX: Some hacks to put a &fn in Scheduler without borrowck
45
- // complaining
46
- type UnsafeTaskReceiver = sys:: Closure ;
47
- trait ClosureConverter {
48
- fn from_fn ( & fn ( ~Coroutine ) ) -> Self ;
49
- fn to_fn ( self ) -> & fn ( ~Coroutine ) ;
44
+ pub struct Coroutine {
45
+ /// The segment of stack on which the task is currently running or,
46
+ /// if the task is blocked, on which the task will resume execution
47
+ priv current_stack_segment : StackSegment ,
48
+ /// These are always valid when the task is not running, unless
49
+ /// the task is dead
50
+ priv saved_context : Context ,
51
+ /// The heap, GC, unwinding, local storage, logging
52
+ task : ~Task
50
53
}
51
- impl ClosureConverter for UnsafeTaskReceiver {
52
- fn from_fn ( f : & fn ( ~ Coroutine ) ) -> UnsafeTaskReceiver { unsafe { transmute ( f ) } }
53
- fn to_fn ( self ) -> & fn ( ~ Coroutine ) { unsafe { transmute ( self ) } }
54
+
55
+ pub struct SchedHandle {
56
+ priv remote : ~ RemoteCallbackObject
54
57
}
55
58
56
59
enum CleanupJob {
@@ -103,6 +106,17 @@ pub impl Scheduler {
103
106
return sched;
104
107
}
105
108
109
+ fn make_handle ( & mut self ) -> SchedHandle {
110
+ let remote = self . event_loop . remote_callback ( wake_up) ;
111
+
112
+ return SchedHandle {
113
+ remote : remote
114
+ } ;
115
+
116
+ fn wake_up ( ) {
117
+ }
118
+ }
119
+
106
120
/// Schedule a task to be executed later.
107
121
///
108
122
/// Pushes the task onto the work stealing queue and tells the event loop
@@ -337,19 +351,6 @@ pub impl Scheduler {
337
351
}
338
352
}
339
353
340
- static MIN_STACK_SIZE : uint = 10000000 ; // XXX: Too much stack
341
-
342
- pub struct Coroutine {
343
- /// The segment of stack on which the task is currently running or,
344
- /// if the task is blocked, on which the task will resume execution
345
- priv current_stack_segment : StackSegment ,
346
- /// These are always valid when the task is not running, unless
347
- /// the task is dead
348
- priv saved_context : Context ,
349
- /// The heap, GC, unwinding, local storage, logging
350
- task : ~Task
351
- }
352
-
353
354
pub impl Coroutine {
354
355
fn new ( stack_pool : & mut StackPool , start : ~fn ( ) ) -> Coroutine {
355
356
Coroutine :: with_task ( stack_pool, ~Task :: new ( ) , start)
@@ -358,6 +359,9 @@ pub impl Coroutine {
358
359
fn with_task ( stack_pool : & mut StackPool ,
359
360
task : ~Task ,
360
361
start : ~fn ( ) ) -> Coroutine {
362
+
363
+ static MIN_STACK_SIZE : uint = 10000000 ; // XXX: Too much stack
364
+
361
365
let start = Coroutine :: build_start_wrapper ( start) ;
362
366
let mut stack = stack_pool. take_segment ( MIN_STACK_SIZE ) ;
363
367
// NB: Context holds a pointer to that ~fn
@@ -401,6 +405,18 @@ pub impl Coroutine {
401
405
}
402
406
}
403
407
408
+ // XXX: Some hacks to put a &fn in Scheduler without borrowck
409
+ // complaining
410
+ type UnsafeTaskReceiver = sys:: Closure ;
411
+ trait ClosureConverter {
412
+ fn from_fn ( & fn ( ~Coroutine ) ) -> Self ;
413
+ fn to_fn ( self ) -> & fn ( ~Coroutine ) ;
414
+ }
415
+ impl ClosureConverter for UnsafeTaskReceiver {
416
+ fn from_fn ( f : & fn ( ~Coroutine ) ) -> UnsafeTaskReceiver { unsafe { transmute ( f) } }
417
+ fn to_fn ( self ) -> & fn ( ~Coroutine ) { unsafe { transmute ( self ) } }
418
+ }
419
+
404
420
#[ cfg( test) ]
405
421
mod test {
406
422
use int;
@@ -411,6 +427,7 @@ mod test {
411
427
use rt:: local:: Local ;
412
428
use rt:: test:: * ;
413
429
use super :: * ;
430
+ use rt:: thread:: Thread ;
414
431
415
432
#[ test]
416
433
fn test_simple_scheduling ( ) {
@@ -551,4 +568,42 @@ mod test {
551
568
}
552
569
}
553
570
}
571
+
572
+ #[ test]
573
+ fn handle ( ) {
574
+ use rt:: comm:: * ;
575
+
576
+ do run_in_bare_thread {
577
+ let ( port, chan) = oneshot :: < ( ) > ( ) ;
578
+ let port_cell = Cell ( port) ;
579
+ let chan_cell = Cell ( chan) ;
580
+ let mut sched1 = ~UvEventLoop :: new_scheduler ( ) ;
581
+ let handle1 = sched1. make_handle ( ) ;
582
+ let handle1_cell = Cell ( handle1) ;
583
+ let task1 = ~do Coroutine :: new ( & mut sched1. stack_pool ) {
584
+ chan_cell. take ( ) . send ( ( ) ) ;
585
+ } ;
586
+ sched1. enqueue_task ( task1) ;
587
+
588
+ let mut sched2 = ~UvEventLoop :: new_scheduler ( ) ;
589
+ let task2 = ~do Coroutine :: new ( & mut sched2. stack_pool ) {
590
+ port_cell. take ( ) . recv ( ) ;
591
+ // Release the other scheduler's handle so it can exit
592
+ handle1_cell. take ( ) ;
593
+ } ;
594
+ sched2. enqueue_task ( task2) ;
595
+
596
+ let sched1_cell = Cell ( sched1) ;
597
+ let _thread1 = do Thread :: start {
598
+ let mut sched1 = sched1_cell. take ( ) ;
599
+ sched1. run ( ) ;
600
+ } ;
601
+
602
+ let sched2_cell = Cell ( sched2) ;
603
+ let _thread2 = do Thread :: start {
604
+ let mut sched2 = sched2_cell. take ( ) ;
605
+ sched2. run ( ) ;
606
+ } ;
607
+ }
608
+ }
554
609
}
0 commit comments