Don't use NoSend/NoSync in libstd
This commit is contained in:
parent
bb04121138
commit
c6ab9a6370
6 changed files with 164 additions and 1 deletions
|
@ -110,6 +110,7 @@
|
||||||
#![feature(slicing_syntax, unboxed_closures)]
|
#![feature(slicing_syntax, unboxed_closures)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(old_impl_check)]
|
#![feature(old_impl_check)]
|
||||||
|
#![feature(optin_builtin_traits)]
|
||||||
#![allow(unknown_features)] #![feature(int_uint)]
|
#![allow(unknown_features)] #![feature(int_uint)]
|
||||||
|
|
||||||
// Don't link to std. We are std.
|
// Don't link to std. We are std.
|
||||||
|
|
|
@ -14,6 +14,7 @@ use thread::Thread;
|
||||||
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
use marker::{Sync, Send};
|
use marker::{Sync, Send};
|
||||||
|
#[cfg(stage0)] // NOTE remove use after next snapshot
|
||||||
use marker::{NoSend, NoSync};
|
use marker::{NoSend, NoSync};
|
||||||
use mem;
|
use mem;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
|
@ -31,12 +32,25 @@ pub struct SignalToken {
|
||||||
inner: Arc<Inner>,
|
inner: Arc<Inner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub struct WaitToken {
|
pub struct WaitToken {
|
||||||
inner: Arc<Inner>,
|
inner: Arc<Inner>,
|
||||||
no_send: NoSend,
|
no_send: NoSend,
|
||||||
no_sync: NoSync,
|
no_sync: NoSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub struct WaitToken {
|
||||||
|
inner: Arc<Inner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl !Send for WaitToken {}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl !Sync for WaitToken {}
|
||||||
|
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub fn tokens() -> (WaitToken, SignalToken) {
|
pub fn tokens() -> (WaitToken, SignalToken) {
|
||||||
let inner = Arc::new(Inner {
|
let inner = Arc::new(Inner {
|
||||||
thread: Thread::current(),
|
thread: Thread::current(),
|
||||||
|
@ -53,6 +67,21 @@ pub fn tokens() -> (WaitToken, SignalToken) {
|
||||||
(wait_token, signal_token)
|
(wait_token, signal_token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub fn tokens() -> (WaitToken, SignalToken) {
|
||||||
|
let inner = Arc::new(Inner {
|
||||||
|
thread: Thread::current(),
|
||||||
|
woken: ATOMIC_BOOL_INIT,
|
||||||
|
});
|
||||||
|
let wait_token = WaitToken {
|
||||||
|
inner: inner.clone(),
|
||||||
|
};
|
||||||
|
let signal_token = SignalToken {
|
||||||
|
inner: inner
|
||||||
|
};
|
||||||
|
(wait_token, signal_token)
|
||||||
|
}
|
||||||
|
|
||||||
impl SignalToken {
|
impl SignalToken {
|
||||||
pub fn signal(&self) -> bool {
|
pub fn signal(&self) -> bool {
|
||||||
let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
|
let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
|
||||||
|
|
|
@ -370,12 +370,24 @@ unsafe impl<T:Send> Send for Sender<T> { }
|
||||||
/// The sending-half of Rust's synchronous channel type. This half can only be
|
/// The sending-half of Rust's synchronous channel type. This half can only be
|
||||||
/// owned by one task, but it can be cloned to send to other tasks.
|
/// owned by one task, but it can be cloned to send to other tasks.
|
||||||
#[stable]
|
#[stable]
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub struct SyncSender<T> {
|
pub struct SyncSender<T> {
|
||||||
inner: Arc<RacyCell<sync::Packet<T>>>,
|
inner: Arc<RacyCell<sync::Packet<T>>>,
|
||||||
// can't share in an arc
|
// can't share in an arc
|
||||||
_marker: marker::NoSync,
|
_marker: marker::NoSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The sending-half of Rust's synchronous channel type. This half can only be
|
||||||
|
/// owned by one task, but it can be cloned to send to other tasks.
|
||||||
|
#[stable]
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub struct SyncSender<T> {
|
||||||
|
inner: Arc<RacyCell<sync::Packet<T>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl<T> !marker::Sync for SyncSender<T> {}
|
||||||
|
|
||||||
/// An error returned from the `send` function on channels.
|
/// An error returned from the `send` function on channels.
|
||||||
///
|
///
|
||||||
/// A `send` operation can only fail if the receiving end of a channel is
|
/// A `send` operation can only fail if the receiving end of a channel is
|
||||||
|
@ -677,10 +689,16 @@ impl<T: Send> Drop for Sender<T> {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl<T: Send> SyncSender<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<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
|
||||||
SyncSender { inner: inner, _marker: marker::NoSync }
|
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> {
|
||||||
|
SyncSender { inner: inner }
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends a value on this synchronous channel.
|
/// Sends a value on this synchronous channel.
|
||||||
///
|
///
|
||||||
/// This function will *block* until space in the internal buffer becomes
|
/// This function will *block* until space in the internal buffer becomes
|
||||||
|
|
|
@ -66,6 +66,7 @@ use sync::mpsc::blocking::{self, SignalToken};
|
||||||
|
|
||||||
/// The "receiver set" of the select interface. This structure is used to manage
|
/// The "receiver set" of the select interface. This structure is used to manage
|
||||||
/// a set of receivers which are being selected over.
|
/// a set of receivers which are being selected over.
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub struct Select {
|
pub struct Select {
|
||||||
head: *mut Handle<'static, ()>,
|
head: *mut Handle<'static, ()>,
|
||||||
tail: *mut Handle<'static, ()>,
|
tail: *mut Handle<'static, ()>,
|
||||||
|
@ -73,6 +74,18 @@ pub struct Select {
|
||||||
marker1: marker::NoSend,
|
marker1: marker::NoSend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The "receiver set" of the select interface. This structure is used to manage
|
||||||
|
/// a set of receivers which are being selected over.
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub struct Select {
|
||||||
|
head: *mut Handle<'static, ()>,
|
||||||
|
tail: *mut Handle<'static, ()>,
|
||||||
|
next_id: Cell<uint>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl !marker::Send for Select {}
|
||||||
|
|
||||||
/// A handle to a receiver which is currently a member of a `Select` set of
|
/// A handle to a receiver which is currently a member of a `Select` set of
|
||||||
/// receivers. This handle is used to keep the receiver in the set as well as
|
/// receivers. This handle is used to keep the receiver in the set as well as
|
||||||
/// interact with the underlying receiver.
|
/// interact with the underlying receiver.
|
||||||
|
@ -113,6 +126,7 @@ impl Select {
|
||||||
///
|
///
|
||||||
/// Usage of this struct directly can sometimes be burdensome, and usage is
|
/// Usage of this struct directly can sometimes be burdensome, and usage is
|
||||||
/// rather much easier through the `select!` macro.
|
/// rather much easier through the `select!` macro.
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub fn new() -> Select {
|
pub fn new() -> Select {
|
||||||
Select {
|
Select {
|
||||||
marker1: marker::NoSend,
|
marker1: marker::NoSend,
|
||||||
|
@ -122,6 +136,20 @@ impl Select {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new selection structure. This set is initially empty and
|
||||||
|
/// `wait` will panic!() if called.
|
||||||
|
///
|
||||||
|
/// Usage of this struct directly can sometimes be burdensome, and usage is
|
||||||
|
/// rather much easier through the `select!` macro.
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub fn new() -> Select {
|
||||||
|
Select {
|
||||||
|
head: 0 as *mut Handle<'static, ()>,
|
||||||
|
tail: 0 as *mut Handle<'static, ()>,
|
||||||
|
next_id: Cell::new(1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new handle into this receiver set for a new receiver. Note
|
/// Creates a new handle into this receiver set for a new receiver. Note
|
||||||
/// that this does *not* add the receiver to the receiver set, for that you
|
/// that this does *not* add the receiver to the receiver set, for that you
|
||||||
/// must call the `add` method on the handle itself.
|
/// must call the `add` method on the handle itself.
|
||||||
|
|
|
@ -160,6 +160,7 @@ unsafe impl Sync for StaticMutex {}
|
||||||
/// Deref and DerefMut implementations
|
/// Deref and DerefMut implementations
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable]
|
#[stable]
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub struct MutexGuard<'a, T: 'a> {
|
pub struct MutexGuard<'a, T: 'a> {
|
||||||
// funny underscores due to how Deref/DerefMut currently work (they
|
// funny underscores due to how Deref/DerefMut currently work (they
|
||||||
// disregard field privacy).
|
// disregard field privacy).
|
||||||
|
@ -169,6 +170,25 @@ pub struct MutexGuard<'a, T: 'a> {
|
||||||
__marker: marker::NoSend,
|
__marker: marker::NoSend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
|
||||||
|
/// dropped (falls out of scope), the lock will be unlocked.
|
||||||
|
///
|
||||||
|
/// The data protected by the mutex can be access through this guard via its
|
||||||
|
/// Deref and DerefMut implementations
|
||||||
|
#[must_use]
|
||||||
|
#[stable]
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub struct MutexGuard<'a, T: 'a> {
|
||||||
|
// funny underscores due to how Deref/DerefMut currently work (they
|
||||||
|
// disregard field privacy).
|
||||||
|
__lock: &'a StaticMutex,
|
||||||
|
__data: &'a UnsafeCell<T>,
|
||||||
|
__poison: poison::Guard,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
|
||||||
|
|
||||||
/// Static initialization of a mutex. This constant can be used to initialize
|
/// Static initialization of a mutex. This constant can be used to initialize
|
||||||
/// other mutex constants.
|
/// other mutex constants.
|
||||||
#[unstable = "may be merged with Mutex in the future"]
|
#[unstable = "may be merged with Mutex in the future"]
|
||||||
|
@ -279,6 +299,7 @@ impl StaticMutex {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mutex, T> MutexGuard<'mutex, T> {
|
impl<'mutex, T> MutexGuard<'mutex, T> {
|
||||||
|
#[cfg(stage0)] // NOTE remove afte next snapshot
|
||||||
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
|
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
|
||||||
-> LockResult<MutexGuard<'mutex, T>> {
|
-> LockResult<MutexGuard<'mutex, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |guard| {
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
|
@ -290,6 +311,18 @@ impl<'mutex, T> MutexGuard<'mutex, T> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg afte next snapshot
|
||||||
|
fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
|
||||||
|
-> LockResult<MutexGuard<'mutex, T>> {
|
||||||
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
|
MutexGuard {
|
||||||
|
__lock: lock,
|
||||||
|
__data: data,
|
||||||
|
__poison: guard,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable]
|
#[stable]
|
||||||
|
|
|
@ -110,23 +110,52 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock {
|
||||||
/// dropped.
|
/// dropped.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable]
|
#[stable]
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
pub struct RwLockReadGuard<'a, T: 'a> {
|
pub struct RwLockReadGuard<'a, T: 'a> {
|
||||||
__lock: &'a StaticRwLock,
|
__lock: &'a StaticRwLock,
|
||||||
__data: &'a UnsafeCell<T>,
|
__data: &'a UnsafeCell<T>,
|
||||||
__marker: marker::NoSend,
|
__marker: marker::NoSend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RAII structure used to release the shared read access of a lock when
|
||||||
|
/// dropped.
|
||||||
|
#[must_use]
|
||||||
|
#[stable]
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
pub struct RwLockReadGuard<'a, T: 'a> {
|
||||||
|
__lock: &'a StaticRwLock,
|
||||||
|
__data: &'a UnsafeCell<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {}
|
||||||
|
|
||||||
|
/// RAII structure used to release the exclusive write access of a lock when
|
||||||
|
/// dropped.
|
||||||
|
#[must_use]
|
||||||
|
#[stable]
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
|
pub struct RwLockWriteGuard<'a, T: 'a> {
|
||||||
|
__lock: &'a StaticRwLock,
|
||||||
|
__data: &'a UnsafeCell<T>,
|
||||||
|
__poison: poison::Guard,
|
||||||
|
__marker: marker::NoSend,
|
||||||
|
}
|
||||||
|
|
||||||
/// RAII structure used to release the exclusive write access of a lock when
|
/// RAII structure used to release the exclusive write access of a lock when
|
||||||
/// dropped.
|
/// dropped.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[stable]
|
#[stable]
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
pub struct RwLockWriteGuard<'a, T: 'a> {
|
pub struct RwLockWriteGuard<'a, T: 'a> {
|
||||||
__lock: &'a StaticRwLock,
|
__lock: &'a StaticRwLock,
|
||||||
__data: &'a UnsafeCell<T>,
|
__data: &'a UnsafeCell<T>,
|
||||||
__poison: poison::Guard,
|
__poison: poison::Guard,
|
||||||
__marker: marker::NoSend,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {}
|
||||||
|
|
||||||
impl<T: Send + Sync> RwLock<T> {
|
impl<T: Send + Sync> RwLock<T> {
|
||||||
/// Creates a new instance of an RwLock which is unlocked and read to go.
|
/// Creates a new instance of an RwLock which is unlocked and read to go.
|
||||||
#[stable]
|
#[stable]
|
||||||
|
@ -303,6 +332,7 @@ impl StaticRwLock {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
|
impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
-> LockResult<RwLockReadGuard<'rwlock, T>> {
|
-> LockResult<RwLockReadGuard<'rwlock, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |_| {
|
poison::map_result(lock.poison.borrow(), |_| {
|
||||||
|
@ -313,8 +343,20 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
|
-> LockResult<RwLockReadGuard<'rwlock, T>> {
|
||||||
|
poison::map_result(lock.poison.borrow(), |_| {
|
||||||
|
RwLockReadGuard {
|
||||||
|
__lock: lock,
|
||||||
|
__data: data,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
||||||
|
#[cfg(stage0)] // NOTE remove impl after next snapshot
|
||||||
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
||||||
poison::map_result(lock.poison.borrow(), |guard| {
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
|
@ -326,6 +368,18 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))] // NOTE remove cfg after next snapshot
|
||||||
|
fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
|
||||||
|
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
|
||||||
|
poison::map_result(lock.poison.borrow(), |guard| {
|
||||||
|
RwLockWriteGuard {
|
||||||
|
__lock: lock,
|
||||||
|
__data: data,
|
||||||
|
__poison: guard,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable]
|
#[stable]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue