@@ -385,17 +385,17 @@ impl<T: Send> Chan<T> {
385385 pub fn try_send ( & self , t : T ) -> bool {
386386 // In order to prevent starvation of other tasks in situations where
387387 // a task sends repeatedly without ever receiving, we occassionally
388- // yield instead of doing a send immediately. Only doing this if
389- // we're doing a rescheduling send, otherwise the caller is
390- // expecting not to context switch.
388+ // yield instead of doing a send immediately.
391389 //
392- // Note that we don't unconditionally attempt to yield because the
393- // TLS overhead can be a bit much.
390+ // Don't unconditionally attempt to yield because the TLS overhead can
391+ // be a bit much, and also use `try_take` instead of `take` because
392+ // there's no reason that this send shouldn't be usable off the
393+ // runtime.
394394 let cnt = self . sends . get ( ) + 1 ;
395395 self . sends . set ( cnt) ;
396396 if cnt % ( RESCHED_FREQ as uint ) == 0 {
397- let task: ~Task = Local :: take ( ) ;
398- task. maybe_yield ( ) ;
397+ let task: Option < ~Task > = Local :: try_take ( ) ;
398+ task. map ( |t| t . maybe_yield ( ) ) ;
399399 }
400400
401401 let ( new_inner, ret) = match self . inner {
@@ -521,12 +521,13 @@ impl<T: Send> Port<T> {
521521 pub fn try_recv ( & self ) -> TryRecvResult < T > {
522522 // If a thread is spinning in try_recv, we should take the opportunity
523523 // to reschedule things occasionally. See notes above in scheduling on
524- // sends for why this doesn't always hit TLS.
524+ // sends for why this doesn't always hit TLS, and also for why this uses
525+ // `try_take` instead of `take`.
525526 let cnt = self . receives . get ( ) + 1 ;
526527 self . receives . set ( cnt) ;
527528 if cnt % ( RESCHED_FREQ as uint ) == 0 {
528- let task: ~Task = Local :: take ( ) ;
529- task. maybe_yield ( ) ;
529+ let task: Option < ~Task > = Local :: try_take ( ) ;
530+ task. map ( |t| t . maybe_yield ( ) ) ;
530531 }
531532
532533 loop {
@@ -1203,4 +1204,42 @@ mod test {
12031204 // wait for the child task to exit before we exit
12041205 p1. recv( ) ;
12051206 } )
1207+
1208+ test ! ( fn sends_off_the_runtime( ) {
1209+ use rt:: thread:: Thread ;
1210+
1211+ let ( p, c) = Chan :: new( ) ;
1212+ let t = Thread :: start( proc( ) {
1213+ for _ in range( 0 , 1000 ) {
1214+ c. send( ( ) ) ;
1215+ }
1216+ } ) ;
1217+ for _ in range( 0 , 1000 ) {
1218+ p. recv( ) ;
1219+ }
1220+ t. join( ) ;
1221+ } )
1222+
1223+ test ! ( fn try_recvs_off_the_runtime( ) {
1224+ use rt:: thread:: Thread ;
1225+
1226+ let ( p, c) = Chan :: new( ) ;
1227+ let ( pdone, cdone) = Chan :: new( ) ;
1228+ let t = Thread :: start( proc( ) {
1229+ let mut hits = 0 ;
1230+ while hits < 10 {
1231+ match p. try_recv( ) {
1232+ Data ( ( ) ) => { hits += 1 ; }
1233+ Empty => { Thread :: yield_now( ) ; }
1234+ Disconnected => return ,
1235+ }
1236+ }
1237+ cdone. send( ( ) ) ;
1238+ } ) ;
1239+ for _ in range( 0 , 10 ) {
1240+ c. send( ( ) ) ;
1241+ }
1242+ t. join( ) ;
1243+ pdone. recv( ) ;
1244+ } )
12061245}
0 commit comments