about summary refs log tree commit diff
path: root/src/libstd/comm
diff options
context:
space:
mode:
authorValerii Hiora <valerii.hiora@gmail.com>2014-05-24 08:01:23 +0300
committerValerii Hiora <valerii.hiora@gmail.com>2014-05-24 08:01:23 +0300
commit41b65d39ab5b4fae52cbcc370b464ba370bedb87 (patch)
treeecc69ac7e75fd8690ddee152a49fcf53621fa353 /src/libstd/comm
parent12e80f1a14195814080300b9ac36e267f8870430 (diff)
downloadrust-41b65d39ab5b4fae52cbcc370b464ba370bedb87.tar.gz
rust-41b65d39ab5b4fae52cbcc370b464ba370bedb87.zip
Fixes problems on systems with opaque mutex
On some systems (iOS for example) mutex is represented by
opaque data structure which doesn't play well with simple
data copy. Therefore mutex should be initialized from
magic static value and filled by OS only when it landed RC.
Diffstat (limited to 'src/libstd/comm')
-rw-r--r--src/libstd/comm/mod.rs22
-rw-r--r--src/libstd/comm/shared.rs14
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().