8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use cell:: Cell ;
12
+ use comm;
11
13
use container:: Container ;
12
14
use iterator:: Iterator ;
13
15
use option:: * ;
@@ -16,6 +18,8 @@ use option::*;
16
18
use rt:: sched:: Scheduler ;
17
19
use rt:: select:: { SelectInner , SelectPortInner } ;
18
20
use rt:: local:: Local ;
21
+ use rt:: rtio:: EventLoop ;
22
+ use task;
19
23
use vec:: { OwnedVector , MutableVector } ;
20
24
21
25
/// Trait for message-passing primitives that can be select()ed on.
@@ -45,6 +49,14 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
45
49
// (If not, we need to unblock from all of them. Length is a placeholder.)
46
50
let mut ready_index = ports. len ( ) ;
47
51
52
+ // XXX: We're using deschedule...and_then in an unsafe way here (see #8132),
53
+ // in that we need to continue mutating the ready_index in the environment
54
+ // after letting the task get woken up. The and_then closure needs to delay
55
+ // the task from resuming until all ports have become blocked_on.
56
+ let ( p, c) = comm:: oneshot ( ) ;
57
+ let p = Cell :: new ( p) ;
58
+ let c = Cell :: new ( c) ;
59
+
48
60
let sched = Local :: take :: < Scheduler > ( ) ;
49
61
do sched. deschedule_running_task_and_then |sched, task| {
50
62
let task_handles = task. make_selectable ( ports. len ( ) ) ;
@@ -57,8 +69,16 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
57
69
break ;
58
70
}
59
71
}
72
+
73
+ let c = Cell :: new ( c. take ( ) ) ;
74
+ do sched. event_loop . callback { c. take ( ) . send_deferred ( ( ) ) }
60
75
}
61
76
77
+ // Unkillable is necessary not because getting killed is dangerous here,
78
+ // but to force the recv not to use the same kill-flag that we used for
79
+ // selecting. Otherwise a user-sender could spuriously wakeup us here.
80
+ do task:: unkillable { p. take ( ) . recv ( ) ; }
81
+
62
82
// Task resumes. Now unblock ourselves from all the ports we blocked on.
63
83
// If the success index wasn't reset, 'take' will just take all of them.
64
84
// Iterate in reverse so the 'earliest' index that's ready gets returned.
0 commit comments