Skip to content

Kill RacyCell in favor of marking SyncSender explicitly Send. #21438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 22, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 17 additions & 34 deletions src/libstd/sync/mpsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ use prelude::v1::*;

use sync::Arc;
use fmt;
#[cfg(stage0)] // NOTE remove use after next snapshot
use marker;
use mem;
use cell::UnsafeCell;
Expand Down Expand Up @@ -372,7 +373,7 @@ unsafe impl<T:Send> Send for Sender<T> { }
#[stable]
#[cfg(stage0)] // NOTE remove impl after next snapshot
pub struct SyncSender<T> {
inner: Arc<RacyCell<sync::Packet<T>>>,
inner: Arc<UnsafeCell<sync::Packet<T>>>,
// can't share in an arc
_marker: marker::NoSync,
}
Expand All @@ -382,11 +383,13 @@ pub struct SyncSender<T> {
#[stable]
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
pub struct SyncSender<T> {
inner: Arc<RacyCell<sync::Packet<T>>>,
inner: Arc<UnsafeCell<sync::Packet<T>>>,
}

unsafe impl<T:Send> Send for SyncSender<T> {}

#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
impl<T> !marker::Sync for SyncSender<T> {}
impl<T> !Sync for SyncSender<T> {}

/// An error returned from the `send` function on channels.
///
Expand Down Expand Up @@ -442,10 +445,10 @@ pub enum TrySendError<T> {
}

enum Flavor<T> {
Oneshot(Arc<RacyCell<oneshot::Packet<T>>>),
Stream(Arc<RacyCell<stream::Packet<T>>>),
Shared(Arc<RacyCell<shared::Packet<T>>>),
Sync(Arc<RacyCell<sync::Packet<T>>>),
Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
Stream(Arc<UnsafeCell<stream::Packet<T>>>),
Shared(Arc<UnsafeCell<shared::Packet<T>>>),
Sync(Arc<UnsafeCell<sync::Packet<T>>>),
}

#[doc(hidden)]
Expand Down Expand Up @@ -497,7 +500,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
/// ```
#[stable]
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
}

Expand Down Expand Up @@ -537,7 +540,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
/// ```
#[stable]
pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
}

Expand Down Expand Up @@ -589,7 +592,7 @@ impl<T: Send> Sender<T> {
return (*p).send(t).map_err(SendError);
} else {
let a =
Arc::new(RacyCell::new(stream::Packet::new()));
Arc::new(UnsafeCell::new(stream::Packet::new()));
let rx = Receiver::new(Flavor::Stream(a.clone()));
match (*p).upgrade(rx) {
oneshot::UpSuccess => {
Expand Down Expand Up @@ -631,7 +634,7 @@ impl<T: Send> Clone for Sender<T> {
fn clone(&self) -> Sender<T> {
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
Flavor::Oneshot(ref p) => {
let a = Arc::new(RacyCell::new(shared::Packet::new()));
let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
unsafe {
let guard = (*a.get()).postinit_lock();
let rx = Receiver::new(Flavor::Shared(a.clone()));
Expand All @@ -643,7 +646,7 @@ impl<T: Send> Clone for Sender<T> {
}
}
Flavor::Stream(ref p) => {
let a = Arc::new(RacyCell::new(shared::Packet::new()));
let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
unsafe {
let guard = (*a.get()).postinit_lock();
let rx = Receiver::new(Flavor::Shared(a.clone()));
Expand Down Expand Up @@ -690,12 +693,12 @@ impl<T: Send> Drop for Sender<T> {

impl<T: Send> SyncSender<T> {
#[cfg(stage0)] // NOTE remove impl after next snapshot
fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
SyncSender { inner: inner, _marker: marker::NoSync }
}

#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
SyncSender { inner: inner }
}

Expand Down Expand Up @@ -978,26 +981,6 @@ impl<T: Send> Drop for Receiver<T> {
}
}

/// A version of `UnsafeCell` intended for use in concurrent data
/// structures (for example, you might put it in an `Arc`).
struct RacyCell<T>(pub UnsafeCell<T>);

impl<T> RacyCell<T> {

fn new(value: T) -> RacyCell<T> {
RacyCell(UnsafeCell { value: value })
}

unsafe fn get(&self) -> *mut T {
self.0.get()
}

}

unsafe impl<T:Send> Send for RacyCell<T> { }

unsafe impl<T> Sync for RacyCell<T> { } // Oh dear

impl<T> fmt::Show for SendError<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"sending on a closed channel".fmt(f)
Expand Down