]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #8327 : sstewartgallus/rust/factor_out_waitqueue, r=bblum
authorbors <bors@rust-lang.org>
Sat, 10 Aug 2013 14:47:14 +0000 (07:47 -0700)
committerbors <bors@rust-lang.org>
Sat, 10 Aug 2013 14:47:14 +0000 (07:47 -0700)
I'm a bit disappointed that I couldn't figure out how to factor out more of the code implementing `extra::sync` but I feel this is an okay start. Also I added some documentation explaining that `WaitQueue` isn't thread safe, and needs an exclusive lock.

@bblum

1  2 
src/libextra/sync.rs

diff --combined src/libextra/sync.rs
index f2a9914cc91a76b2a41658ad053da7d90460a8de,3bdb16a13d21aa30314f48bfcefc51a5e622680c..756a5c7da006594a0efcec42dcdaf2ffe83c21e0
@@@ -19,7 -19,6 +19,7 @@@
  use std::borrow;
  use std::comm;
  use std::comm::SendDeferred;
 +use std::comm::{GenericPort, Peekable};
  use std::task;
  use std::unstable::sync::{Exclusive, UnsafeAtomicRcBox};
  use std::unstable::atomics;
@@@ -72,6 -71,12 +72,12 @@@ impl WaitQueue 
          }
          count
      }
+     fn wait_end(&self) -> WaitEnd {
+         let (wait_end, signal_end) = comm::oneshot();
+         self.tail.send_deferred(signal_end);
+         wait_end
+     }
  }
  
  // The building-block used to make semaphores, mutexes, and rwlocks.
@@@ -100,19 -105,16 +106,16 @@@ impl<Q:Send> Sem<Q> 
              do (**self).with |state| {
                  state.count -= 1;
                  if state.count < 0 {
-                     // Create waiter nobe.
-                     let (WaitEnd, SignalEnd) = comm::oneshot();
-                     // Tell outer scope we need to block.
-                     waiter_nobe = Some(WaitEnd);
-                     // Enqueue ourself.
-                     state.waiters.tail.send_deferred(SignalEnd);
+                     // Create waiter nobe, enqueue ourself, and tell
+                     // outer scope we need to block.
+                     waiter_nobe = Some(state.waiters.wait_end());
                  }
              }
              // Uncomment if you wish to test for sem races. Not valgrind-friendly.
              /* do 1000.times { task::yield(); } */
              // Need to wait outside the exclusive.
              if waiter_nobe.is_some() {
 -                let _ = comm::recv_one(waiter_nobe.unwrap());
 +                let _ = waiter_nobe.unwrap().recv();
              }
          }
      }
@@@ -201,10 -203,7 +204,7 @@@ impl<'self> Condvar<'self> 
       * wait() is equivalent to wait_on(0).
       */
      pub fn wait_on(&self, condvar_id: uint) {
-         // Create waiter nobe.
-         let (WaitEnd, SignalEnd) = comm::oneshot();
-         let mut WaitEnd   = Some(WaitEnd);
-         let mut SignalEnd = Some(SignalEnd);
+         let mut WaitEnd = None;
          let mut out_of_bounds = None;
          do task::unkillable {
              // Release lock, 'atomically' enqueuing ourselves in so doing.
                          if state.count <= 0 {
                              state.waiters.signal();
                          }
-                         // Enqueue ourself to be woken up by a signaller.
-                         let SignalEnd = SignalEnd.take_unwrap();
-                         state.blocked[condvar_id].tail.send_deferred(SignalEnd);
+                         // Create waiter nobe, and enqueue ourself to
+                         // be woken up by a signaller.
+                         WaitEnd = Some(state.blocked[condvar_id].wait_end());
                      } else {
                          out_of_bounds = Some(state.blocked.len());
                      }
                  do (|| {
                      unsafe {
                          do task::rekillable {
 -                            let _ = comm::recv_one(WaitEnd.take_unwrap());
 +                            let _ = WaitEnd.take_unwrap().recv();
                          }
                      }
                  }).finally {