88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11+ use cell:: Cell ;
12+ use comm;
1113use container:: Container ;
1214use iterator:: Iterator ;
1315use option:: * ;
@@ -16,6 +18,8 @@ use option::*;
1618use rt:: sched:: Scheduler ;
1719use rt:: select:: { SelectInner , SelectPortInner } ;
1820use rt:: local:: Local ;
21+ use rt:: rtio:: EventLoop ;
22+ use task;
1923use vec:: { OwnedVector , MutableVector } ;
2024
2125/// Trait for message-passing primitives that can be select()ed on.
@@ -45,6 +49,14 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
4549 // (If not, we need to unblock from all of them. Length is a placeholder.)
4650 let mut ready_index = ports. len ( ) ;
4751
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+
4860 let sched = Local :: take :: < Scheduler > ( ) ;
4961 do sched. deschedule_running_task_and_then |sched, task| {
5062 let task_handles = task. make_selectable ( ports. len ( ) ) ;
@@ -57,8 +69,16 @@ pub fn select<A: Select>(ports: &mut [A]) -> uint {
5769 break ;
5870 }
5971 }
72+
73+ let c = Cell :: new ( c. take ( ) ) ;
74+ do sched. event_loop . callback { c. take ( ) . send_deferred ( ( ) ) }
6075 }
6176
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+
6282 // Task resumes. Now unblock ourselves from all the ports we blocked on.
6383 // If the success index wasn't reset, 'take' will just take all of them.
6484 // Iterate in reverse so the 'earliest' index that's ready gets returned.
0 commit comments