Make Barrier and Condvar Sync/Send
This commit is contained in:
parent
607f60712c
commit
d35ebcb483
|
@ -180,12 +180,12 @@ mod tests {
|
|||
|
||||
fn malloc(n: uint) -> CVec<u8> {
|
||||
unsafe {
|
||||
let mem = libc::malloc(n as libc::size_t);
|
||||
if mem.is_null() { ::alloc::oom() }
|
||||
let mem = ptr::Unique(libc::malloc(n as libc::size_t));
|
||||
if mem.0.is_null() { ::alloc::oom() }
|
||||
|
||||
CVec::new_with_dtor(mem as *mut u8,
|
||||
CVec::new_with_dtor(mem.0 as *mut u8,
|
||||
n,
|
||||
move|| { libc::free(mem as *mut libc::c_void); })
|
||||
move|| { libc::free(mem.0 as *mut libc::c_void); })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use kinds::{Send, Sync};
|
||||
use sync::{Mutex, Condvar};
|
||||
|
||||
/// A barrier enables multiple tasks to synchronize the beginning
|
||||
|
@ -35,12 +36,18 @@ pub struct Barrier {
|
|||
num_threads: uint,
|
||||
}
|
||||
|
||||
unsafe impl Send for Barrier {}
|
||||
unsafe impl Sync for Barrier {}
|
||||
|
||||
// The inner state of a double barrier
|
||||
struct BarrierState {
|
||||
count: uint,
|
||||
generation_id: uint,
|
||||
}
|
||||
|
||||
unsafe impl Send for BarrierState {}
|
||||
unsafe impl Sync for BarrierState {}
|
||||
|
||||
impl Barrier {
|
||||
/// Create a new barrier that can block a given number of threads.
|
||||
///
|
||||
|
|
|
@ -58,6 +58,9 @@ use time::Duration;
|
|||
/// ```
|
||||
pub struct Condvar { inner: Box<StaticCondvar> }
|
||||
|
||||
unsafe impl Send for Condvar {}
|
||||
unsafe impl Sync for Condvar {}
|
||||
|
||||
/// Statically allocated condition variables.
|
||||
///
|
||||
/// This structure is identical to `Condvar` except that it is suitable for use
|
||||
|
@ -75,6 +78,9 @@ pub struct StaticCondvar {
|
|||
mutex: AtomicUint,
|
||||
}
|
||||
|
||||
unsafe impl Send for StaticCondvar {}
|
||||
unsafe impl Sync for StaticCondvar {}
|
||||
|
||||
/// Constant initializer for a statically allocated condition variable.
|
||||
pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
|
||||
inner: sys::CONDVAR_INIT,
|
||||
|
|
|
@ -284,6 +284,11 @@ mod test {
|
|||
use thread::Thread;
|
||||
use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
|
||||
|
||||
struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
|
||||
|
||||
unsafe impl<T:'static+Send> Send for Packet<T> {}
|
||||
unsafe impl<T> Sync for Packet<T> {}
|
||||
|
||||
#[test]
|
||||
fn smoke() {
|
||||
let m = Mutex::new(());
|
||||
|
@ -343,19 +348,19 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_mutex_arc_condvar() {
|
||||
let arc = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let arc2 = arc.clone();
|
||||
let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
|
||||
let packet2 = Packet(packet.0.clone());
|
||||
let (tx, rx) = channel();
|
||||
spawn(move|| {
|
||||
// wait until parent gets in
|
||||
rx.recv();
|
||||
let &(ref lock, ref cvar) = &*arc2;
|
||||
let &(ref lock, ref cvar) = &*packet2.0;
|
||||
let mut lock = lock.lock();
|
||||
*lock = true;
|
||||
cvar.notify_one();
|
||||
});
|
||||
|
||||
let &(ref lock, ref cvar) = &*arc;
|
||||
let &(ref lock, ref cvar) = &*packet.0;
|
||||
let lock = lock.lock();
|
||||
tx.send(());
|
||||
assert!(!*lock);
|
||||
|
@ -367,20 +372,20 @@ mod test {
|
|||
#[test]
|
||||
#[should_fail]
|
||||
fn test_arc_condvar_poison() {
|
||||
let arc = Arc::new((Mutex::new(1i), Condvar::new()));
|
||||
let arc2 = arc.clone();
|
||||
let packet = Packet(Arc::new((Mutex::new(1i), Condvar::new())));
|
||||
let packet2 = Packet(packet.0.clone());
|
||||
let (tx, rx) = channel();
|
||||
|
||||
spawn(move|| {
|
||||
rx.recv();
|
||||
let &(ref lock, ref cvar) = &*arc2;
|
||||
let &(ref lock, ref cvar) = &*packet2.0;
|
||||
let _g = lock.lock();
|
||||
cvar.notify_one();
|
||||
// Parent should fail when it wakes up.
|
||||
panic!();
|
||||
});
|
||||
|
||||
let &(ref lock, ref cvar) = &*arc;
|
||||
let &(ref lock, ref cvar) = &*packet.0;
|
||||
let lock = lock.lock();
|
||||
tx.send(());
|
||||
while *lock == 1 {
|
||||
|
|
|
@ -60,6 +60,9 @@ pub struct RWLock<T> {
|
|||
data: UnsafeCell<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T:'static+Send> Send for RWLock<T> {}
|
||||
unsafe impl<T> Sync for RWLock<T> {}
|
||||
|
||||
/// Structure representing a statically allocated RWLock.
|
||||
///
|
||||
/// This structure is intended to be used inside of a `static` and will provide
|
||||
|
@ -88,6 +91,9 @@ pub struct StaticRWLock {
|
|||
poison: UnsafeCell<poison::Flag>,
|
||||
}
|
||||
|
||||
unsafe impl Send for StaticRWLock {}
|
||||
unsafe impl Sync for StaticRWLock {}
|
||||
|
||||
/// Constant initialization for a statically-initialized rwlock.
|
||||
pub const RWLOCK_INIT: StaticRWLock = StaticRWLock {
|
||||
inner: sys::RWLOCK_INIT,
|
||||
|
|
Loading…
Reference in New Issue