diff options
Diffstat (limited to 'src/libstd/comm')
| -rw-r--r-- | src/libstd/comm/mod.rs | 22 | ||||
| -rw-r--r-- | src/libstd/comm/shared.rs | 14 |
2 files changed, 23 insertions, 13 deletions
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs index b2521f2978a..18857e221fa 100644 --- a/src/libstd/comm/mod.rs +++ b/src/libstd/comm/mod.rs @@ -600,20 +600,22 @@ impl<T: Send> Clone for Sender<T> { let (packet, sleeper) = match *unsafe { self.inner() } { Oneshot(ref p) => { let a = Arc::new(Unsafe::new(shared::Packet::new())); - match unsafe { - (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) - } { - oneshot::UpSuccess | oneshot::UpDisconnected => (a, None), - oneshot::UpWoke(task) => (a, Some(task)) + unsafe { + (*a.get()).postinit_lock(); + match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) { + oneshot::UpSuccess | oneshot::UpDisconnected => (a, None), + oneshot::UpWoke(task) => (a, Some(task)) + } } } Stream(ref p) => { let a = Arc::new(Unsafe::new(shared::Packet::new())); - match unsafe { - (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) - } { - stream::UpSuccess | stream::UpDisconnected => (a, None), - stream::UpWoke(task) => (a, Some(task)), + unsafe { + (*a.get()).postinit_lock(); + match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) { + stream::UpSuccess | stream::UpDisconnected => (a, None), + stream::UpWoke(task) => (a, Some(task)), + } } } Shared(ref p) => { diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs index 8aef2ec80a8..3fde584a46f 100644 --- a/src/libstd/comm/shared.rs +++ b/src/libstd/comm/shared.rs @@ -66,7 +66,8 @@ pub enum Failure { } impl<T: Send> Packet<T> { - // Creation of a packet *must* be followed by a call to inherit_blocker + // Creation of a packet *must* be followed by a call to postinit_lock + // and later by inherit_blocker pub fn new() -> Packet<T> { let p = Packet { queue: mpsc::Queue::new(), @@ -78,11 +79,18 @@ impl<T: Send> Packet<T> { sender_drain: atomics::AtomicInt::new(0), select_lock: unsafe { NativeMutex::new() }, }; - // see comments in inherit_blocker about why we grab this lock - unsafe { p.select_lock.lock_noguard() } return p; } + // This function should be used after newly created Packet + // was wrapped with an Arc + // In other case mutex data will be duplicated while clonning + // and that could cause problems on platforms where it is + // represented by opaque data structure + pub fn postinit_lock(&mut self) { + unsafe { self.select_lock.lock_noguard() } + } + // This function is used at the creation of a shared packet to inherit a // previously blocked task. This is done to prevent spurious wakeups of // tasks in select(). |
