Relax Arc bounds don't require Sync+Send

Besides the above making sense, it'll also allow us to make `RacyCell`
private and use UnsafeCell instead.
This commit is contained in:
Flavio Percoco 2014-12-22 17:15:51 +01:00
parent 7df17a2868
commit 8818693496
7 changed files with 37 additions and 36 deletions

View file

@ -139,7 +139,7 @@ struct ArcInner<T> {
data: T,
}
impl<T: Sync + Send> Arc<T> {
impl<T> Arc<T> {
/// Constructs a new `Arc<T>`.
///
/// # Examples

View file

@ -1027,23 +1027,18 @@ fn drop(&mut self) {
/// A version of `UnsafeCell` intended for use in concurrent data
/// structures (for example, you might put it in an `Arc`).
pub struct RacyCell<T>(pub UnsafeCell<T>);
struct RacyCell<T>(pub UnsafeCell<T>);
impl<T> RacyCell<T> {
/// DOX
pub fn new(value: T) -> RacyCell<T> {
fn new(value: T) -> RacyCell<T> {
RacyCell(UnsafeCell { value: value })
}
/// DOX
pub unsafe fn get(&self) -> *mut T {
unsafe fn get(&self) -> *mut T {
self.0.get()
}
/// DOX
pub unsafe fn into_inner(self) -> T {
self.0.into_inner()
}
}
unsafe impl<T:Send> Send for RacyCell<T> { }

View file

@ -10,7 +10,6 @@
use prelude::*;
use comm::RacyCell;
use cell::UnsafeCell;
use kinds::marker;
use sync::{poison, AsMutexGuard};
@ -71,7 +70,7 @@ pub struct Mutex<T> {
// time, so to ensure that the native mutex is used correctly we box the
// inner lock to give it a constant address.
inner: Box<StaticMutex>,
data: RacyCell<T>,
data: UnsafeCell<T>,
}
unsafe impl<T:Send> Send for Mutex<T> { }
@ -101,7 +100,7 @@ unsafe impl<T:Send> Sync for Mutex<T> { }
/// ```
pub struct StaticMutex {
lock: sys::Mutex,
poison: RacyCell<poison::Flag>,
poison: UnsafeCell<poison::Flag>,
}
unsafe impl Sync for StaticMutex {}
@ -132,7 +131,7 @@ pub struct StaticMutexGuard {
/// other mutex constants.
pub const MUTEX_INIT: StaticMutex = StaticMutex {
lock: sys::MUTEX_INIT,
poison: RacyCell(UnsafeCell { value: poison::Flag { failed: false } }),
poison: UnsafeCell { value: poison::Flag { failed: false } },
};
impl<T: Send> Mutex<T> {
@ -140,7 +139,7 @@ impl<T: Send> Mutex<T> {
pub fn new(t: T) -> Mutex<T> {
Mutex {
inner: box MUTEX_INIT,
data: RacyCell::new(t),
data: UnsafeCell::new(t),
}
}

View file

@ -8,13 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use comm::RacyCell;
use cell::UnsafeCell;
use kinds::Sync;
use sys::sync as ffi;
use sys_common::mutex;
pub struct Mutex { inner: RacyCell<ffi::pthread_mutex_t> }
pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
#[inline]
pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
@ -22,7 +21,7 @@ pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
}
pub const MUTEX_INIT: Mutex = Mutex {
inner: RacyCell(UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }),
inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
};
unsafe impl Sync for Mutex {}

View file

@ -127,7 +127,7 @@
use any::Any;
use borrow::IntoCow;
use boxed::Box;
use comm::RacyCell;
use cell::UnsafeCell;
use clone::Clone;
use kinds::{Send, Sync};
use ops::{Drop, FnOnce};
@ -211,8 +211,8 @@ pub fn spawn<T, F>(self, f: F) -> JoinGuard<T> where
}
fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
let my_packet = Arc::new(RacyCell::new(None));
let their_packet = my_packet.clone();
let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
let their_packet = Packet(my_packet.0.clone());
let Builder { name, stack_size, stdout, stderr } = self;
@ -266,7 +266,7 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> JoinGuard<T> {
}
};
unsafe {
*their_packet.get() = Some(match (output, try_result) {
*their_packet.0.get() = Some(match (output, try_result) {
(Some(data), Ok(_)) => Ok(data),
(None, Err(cause)) => Err(cause),
_ => unreachable!()
@ -383,6 +383,11 @@ fn new(name: Option<String>) -> Thread { Thread::new(name) }
/// A thread that completes without panicking is considered to exit successfully.
pub type Result<T> = ::result::Result<T, Box<Any + Send>>;
struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
unsafe impl<T:'static+Send> Send for Packet<T> {}
unsafe impl<T> Sync for Packet<T> {}
#[must_use]
/// An RAII-style guard that will block until thread termination when dropped.
///
@ -391,9 +396,11 @@ pub struct JoinGuard<T> {
native: imp::rust_thread,
thread: Thread,
joined: bool,
packet: Arc<RacyCell<Option<Result<T>>>>,
packet: Packet<T>,
}
unsafe impl<T: Send> Sync for JoinGuard<T> {}
impl<T: Send> JoinGuard<T> {
/// Extract a handle to the thread this guard will join on.
pub fn thread(&self) -> &Thread {
@ -410,7 +417,7 @@ pub fn join(mut self) -> Result<T> {
unsafe { imp::join(self.native) };
self.joined = true;
unsafe {
(*self.packet.get()).take().unwrap()
(*self.packet.0.get()).take().unwrap()
}
}

View file

@ -196,10 +196,10 @@ pub fn is_set(&'static self) -> bool {
#[cfg(not(any(windows, target_os = "android", target_os = "ios")))]
mod imp {
use std::comm::RacyCell;
use std::cell::UnsafeCell;
#[doc(hidden)]
pub struct KeyInner<T> { pub inner: RacyCell<*mut T> }
pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
unsafe impl<T> ::kinds::Sync for KeyInner<T> { }

View file

@ -9,29 +9,32 @@
// except according to those terms.
use std::kinds::marker;
use std::comm::RacyCell;
use std::cell::UnsafeCell;
struct MyUnsafe<T> {
value: RacyCell<T>
value: UnsafeCell<T>
}
impl<T> MyUnsafe<T> {
fn forbidden(&self) {}
}
impl<T: Send> Sync for MyUnsafe<T> {}
enum UnsafeEnum<T> {
VariantSafe,
VariantUnsafe(RacyCell<T>)
VariantUnsafe(UnsafeCell<T>)
}
impl<T: Send> Sync for UnsafeEnum<T> {}
static STATIC1: UnsafeEnum<int> = UnsafeEnum::VariantSafe;
static STATIC2: RacyCell<int> = RacyCell(UnsafeCell { value: 1 });
const CONST: RacyCell<int> = RacyCell(UnsafeCell { value: 1 });
static STATIC2: UnsafeCell<int> = UnsafeCell { value: 1 };
const CONST: UnsafeCell<int> = UnsafeCell { value: 1 };
static STATIC3: MyUnsafe<int> = MyUnsafe{value: CONST};
static STATIC4: &'static RacyCell<int> = &STATIC2;
static STATIC4: &'static UnsafeCell<int> = &STATIC2;
struct Wrap<T> {
value: T
@ -39,13 +42,11 @@ struct Wrap<T> {
unsafe impl<T: Send> Sync for Wrap<T> {}
static UNSAFE: RacyCell<int> = RacyCell(UnsafeCell{value: 1});
static WRAPPED_UNSAFE: Wrap<&'static RacyCell<int>> = Wrap { value: &UNSAFE };
static UNSAFE: UnsafeCell<int> = UnsafeCell{value: 1};
static WRAPPED_UNSAFE: Wrap<&'static UnsafeCell<int>> = Wrap { value: &UNSAFE };
fn main() {
let a = &STATIC1;
STATIC3.forbidden()
}