Make Send and Sync traits unsafe

This commit is contained in:
Flavio Percoco 2014-12-22 00:49:42 +01:00
parent 686ce664da
commit f436f9ca29
32 changed files with 73 additions and 55 deletions

View File

@ -129,9 +129,9 @@ pub struct Weak<T> {
_ptr: *mut ArcInner<T>, _ptr: *mut ArcInner<T>,
} }
impl<T: Sync + Send> Send for Arc<T> { } unsafe impl<T: Sync + Send> Send for Arc<T> { }
impl<T: Sync + Send> Sync for Arc<T> { } unsafe impl<T: Sync + Send> Sync for Arc<T> { }
struct ArcInner<T> { struct ArcInner<T> {
strong: atomic::AtomicUint, strong: atomic::AtomicUint,

View File

@ -577,6 +577,6 @@ impl<T> RacyCell<T> {
} }
} }
impl<T:Send> Send for RacyCell<T> { } unsafe impl<T:Send> Send for RacyCell<T> { }
impl<T> Sync for RacyCell<T> { } // Oh dear unsafe impl<T> Sync for RacyCell<T> { } // Oh dear

View File

@ -19,7 +19,7 @@
/// Types able to be transferred across task boundaries. /// Types able to be transferred across task boundaries.
#[lang="send"] #[lang="send"]
pub trait Send for Sized? : 'static { pub unsafe trait Send for Sized? : 'static {
// empty. // empty.
} }
@ -81,7 +81,7 @@ pub trait Copy for Sized? {
/// reference; not doing this is undefined behaviour (for example, /// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal). /// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="sync"] #[lang="sync"]
pub trait Sync for Sized? { pub unsafe trait Sync for Sized? {
// Empty // Empty
} }

View File

@ -515,13 +515,13 @@ pub struct UniquePtr<T>(pub *mut T);
/// reference is unaliased. Note that this aliasing invariant is /// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the /// unenforced by the type system; the abstraction using the
/// `UniquePtr` must enforce it. /// `UniquePtr` must enforce it.
impl<T:Send> Send for UniquePtr<T> { } unsafe impl<T:Send> Send for UniquePtr<T> { }
/// `UniquePtr` pointers are `Sync` if `T` is `Sync` because the data they /// `UniquePtr` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is /// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the /// unenforced by the type system; the abstraction using the
/// `UniquePtr` must enforce it. /// `UniquePtr` must enforce it.
impl<T:Sync> Sync for UniquePtr<T> { } unsafe impl<T:Sync> Sync for UniquePtr<T> { }
impl<T> UniquePtr<T> { impl<T> UniquePtr<T> {
/// Returns a null UniquePtr. /// Returns a null UniquePtr.

View File

@ -281,7 +281,7 @@ struct ModuleConfig {
time_passes: bool, time_passes: bool,
} }
impl Send for ModuleConfig { } unsafe impl Send for ModuleConfig { }
impl ModuleConfig { impl ModuleConfig {
fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig { fn new(tm: TargetMachineRef, passes: Vec<String>) -> ModuleConfig {

View File

@ -60,8 +60,8 @@ pub struct ModuleTranslation {
pub llmod: ModuleRef, pub llmod: ModuleRef,
} }
impl Send for ModuleTranslation { } unsafe impl Send for ModuleTranslation { }
impl Sync for ModuleTranslation { } unsafe impl Sync for ModuleTranslation { }
pub struct CrateTranslation { pub struct CrateTranslation {
pub modules: Vec<ModuleTranslation>, pub modules: Vec<ModuleTranslation>,

View File

@ -89,8 +89,8 @@ pub struct CString {
owns_buffer_: bool, owns_buffer_: bool,
} }
impl Send for CString { } unsafe impl Send for CString { }
impl Sync for CString { } unsafe impl Sync for CString { }
impl Clone for CString { impl Clone for CString {
/// Clone this CString into a new, uniquely owned CString. For safety /// Clone this CString into a new, uniquely owned CString. For safety

View File

@ -13,16 +13,19 @@
use thread::Thread; use thread::Thread;
use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering}; use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering};
use sync::Arc; use sync::Arc;
use kinds::{Sync, Send};
use kinds::marker::{NoSend, NoSync}; use kinds::marker::{NoSend, NoSync};
use mem; use mem;
use clone::Clone; use clone::Clone;
#[deriving(Send, Sync)]
struct Inner { struct Inner {
thread: Thread, thread: Thread,
woken: AtomicBool, woken: AtomicBool,
} }
unsafe impl Send for Inner {}
unsafe impl Sync for Inner {}
#[deriving(Clone)] #[deriving(Clone)]
pub struct SignalToken { pub struct SignalToken {
inner: Arc<Inner>, inner: Arc<Inner>,

View File

@ -363,7 +363,7 @@ pub struct Receiver<T> {
// The receiver port can be sent from place to place, so long as it // The receiver port can be sent from place to place, so long as it
// is not used to receive non-sendable things. // is not used to receive non-sendable things.
impl<T:Send> Send for Receiver<T> { } unsafe impl<T:Send> Send for Receiver<T> { }
/// An iterator over messages on a receiver, this iterator will block /// An iterator over messages on a receiver, this iterator will block
/// whenever `next` is called, waiting for a new message, and `None` will be /// whenever `next` is called, waiting for a new message, and `None` will be
@ -382,7 +382,7 @@ pub struct Sender<T> {
// The send port can be sent from place to place, so long as it // The send port can be sent from place to place, so long as it
// is not used to send non-sendable things. // is not used to send non-sendable things.
impl<T:Send> Send for Sender<T> { } 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.

View File

@ -76,8 +76,8 @@ pub struct Queue<T> {
tail: UnsafeCell<*mut Node<T>>, tail: UnsafeCell<*mut Node<T>>,
} }
impl<T:Send> Send for Queue<T> { } unsafe impl<T:Send> Send for Queue<T> { }
impl<T:Send> Sync for Queue<T> { } unsafe impl<T:Send> Sync for Queue<T> { }
impl<T> Node<T> { impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut Node<T> { unsafe fn new(v: Option<T>) -> *mut Node<T> {

View File

@ -73,9 +73,9 @@ pub struct Queue<T> {
cache_subtractions: AtomicUint, cache_subtractions: AtomicUint,
} }
impl<T: Send> Send for Queue<T> { } unsafe impl<T: Send> Send for Queue<T> { }
impl<T: Send> Sync for Queue<T> { } unsafe impl<T: Send> Sync for Queue<T> { }
impl<T: Send> Node<T> { impl<T: Send> Node<T> {
fn new() -> *mut Node<T> { fn new() -> *mut Node<T> {

View File

@ -53,11 +53,10 @@ pub struct Packet<T> {
lock: Mutex<State<T>>, lock: Mutex<State<T>>,
} }
impl<T:Send> Send for Packet<T> { } unsafe impl<T:Send> Send for Packet<T> { }
impl<T:Send> Sync for Packet<T> { } unsafe impl<T:Send> Sync for Packet<T> { }
#[deriving(Send)]
struct State<T> { struct State<T> {
disconnected: bool, // Is the channel disconnected yet? disconnected: bool, // Is the channel disconnected yet?
queue: Queue, // queue of senders waiting to send data queue: Queue, // queue of senders waiting to send data
@ -74,6 +73,8 @@ struct State<T> {
canceled: Option<&'static mut bool>, canceled: Option<&'static mut bool>,
} }
unsafe impl<T: Send> Send for State<T> {}
/// Possible flavors of threads who can be blocked on this channel. /// Possible flavors of threads who can be blocked on this channel.
enum Blocker { enum Blocker {
BlockedSender(SignalToken), BlockedSender(SignalToken),
@ -93,7 +94,7 @@ struct Node {
next: *mut Node, next: *mut Node,
} }
impl Send for Node {} unsafe impl Send for Node {}
/// A simple ring-buffer /// A simple ring-buffer
struct Buffer<T> { struct Buffer<T> {

View File

@ -26,9 +26,9 @@ pub struct Exclusive<T> {
data: UnsafeCell<T>, data: UnsafeCell<T>,
} }
impl<T:Send> Send for Exclusive<T> { } unsafe impl<T:Send> Send for Exclusive<T> { }
impl<T:Send> Sync for Exclusive<T> { } unsafe impl<T:Send> Sync for Exclusive<T> { }
/// An RAII guard returned via `lock` /// An RAII guard returned via `lock`
pub struct ExclusiveGuard<'a, T:'a> { pub struct ExclusiveGuard<'a, T:'a> {

View File

@ -11,7 +11,7 @@
use prelude::*; use prelude::*;
use cell::{UnsafeCell, RacyCell}; use cell::{UnsafeCell, RacyCell};
use kinds::marker; use kinds::{marker, Sync};
use sync::{poison, AsMutexGuard}; use sync::{poison, AsMutexGuard};
use sys_common::mutex as sys; use sys_common::mutex as sys;
@ -73,9 +73,9 @@ pub struct Mutex<T> {
data: RacyCell<T>, data: RacyCell<T>,
} }
impl<T:Send> Send for Mutex<T> { } unsafe impl<T:Send> Send for Mutex<T> { }
impl<T:Send> Sync for Mutex<T> { } unsafe impl<T:Send> Sync for Mutex<T> { }
/// The static mutex type is provided to allow for static allocation of mutexes. /// The static mutex type is provided to allow for static allocation of mutexes.
/// ///
@ -98,12 +98,13 @@ impl<T:Send> Sync for Mutex<T> { }
/// } /// }
/// // lock is unlocked here. /// // lock is unlocked here.
/// ``` /// ```
#[deriving(Sync)]
pub struct StaticMutex { pub struct StaticMutex {
lock: sys::Mutex, lock: sys::Mutex,
poison: RacyCell<poison::Flag>, poison: RacyCell<poison::Flag>,
} }
unsafe impl Sync for StaticMutex {}
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
/// dropped (falls out of scope), the lock will be unlocked. /// dropped (falls out of scope), the lock will be unlocked.
/// ///

View File

@ -14,6 +14,7 @@
//! example use case would be for initializing an FFI library. //! example use case would be for initializing an FFI library.
use int; use int;
use kinds::Sync;
use mem::drop; use mem::drop;
use ops::FnOnce; use ops::FnOnce;
use sync::atomic; use sync::atomic;
@ -35,13 +36,14 @@ use sync::{StaticMutex, MUTEX_INIT};
/// // run initialization here /// // run initialization here
/// }); /// });
/// ``` /// ```
#[deriving(Sync)]
pub struct Once { pub struct Once {
mutex: StaticMutex, mutex: StaticMutex,
cnt: atomic::AtomicInt, cnt: atomic::AtomicInt,
lock_cnt: atomic::AtomicInt, lock_cnt: atomic::AtomicInt,
} }
unsafe impl Sync for Once {}
/// Initialization value for static `Once` values. /// Initialization value for static `Once` values.
pub const ONCE_INIT: Once = Once { pub const ONCE_INIT: Once = Once {
mutex: MUTEX_INIT, mutex: MUTEX_INIT,

View File

@ -59,9 +59,9 @@ pub struct Helper<M> {
pub shutdown: UnsafeCell<bool>, pub shutdown: UnsafeCell<bool>,
} }
impl<M:Send> Send for Helper<M> { } unsafe impl<M:Send> Send for Helper<M> { }
impl<M:Send> Sync for Helper<M> { } unsafe impl<M:Send> Sync for Helper<M> { }
impl<M: Send> Helper<M> { impl<M: Send> Helper<M> {
/// Lazily boots a helper thread, becoming a no-op if the helper has already /// Lazily boots a helper thread, becoming a no-op if the helper has already

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use kinds::Sync;
use sys::mutex as imp; use sys::mutex as imp;
/// An OS-based mutual exclusion lock. /// An OS-based mutual exclusion lock.
@ -15,9 +16,10 @@ use sys::mutex as imp;
/// This is the thinnest cross-platform wrapper around OS mutexes. All usage of /// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
/// this mutex is unsafe and it is recommended to instead use the safe wrapper /// this mutex is unsafe and it is recommended to instead use the safe wrapper
/// at the top level of the crate instead of this type. /// at the top level of the crate instead of this type.
#[deriving(Sync)]
pub struct Mutex(imp::Mutex); pub struct Mutex(imp::Mutex);
unsafe impl Sync for Mutex {}
/// Constant initializer for statically allocated mutexes. /// Constant initializer for statically allocated mutexes.
pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT); pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);

View File

@ -162,8 +162,8 @@ mod signal {
sa_restorer: *mut libc::c_void, sa_restorer: *mut libc::c_void,
} }
impl ::kinds::Send for sigaction { } unsafe impl ::kinds::Send for sigaction { }
impl ::kinds::Sync for sigaction { } unsafe impl ::kinds::Sync for sigaction { }
#[repr(C)] #[repr(C)]
#[cfg(target_word_size = "32")] #[cfg(target_word_size = "32")]

View File

@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use kinds::Sync;
use cell::{UnsafeCell, RacyCell}; use cell::{UnsafeCell, RacyCell};
use sys::sync as ffi; use sys::sync as ffi;
use sys_common::mutex; use sys_common::mutex;
#[deriving(Sync)]
pub struct Mutex { inner: RacyCell<ffi::pthread_mutex_t> } pub struct Mutex { inner: RacyCell<ffi::pthread_mutex_t> }
#[inline] #[inline]
@ -24,6 +24,8 @@ pub const MUTEX_INIT: Mutex = Mutex {
inner: RacyCell(UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }), inner: RacyCell(UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER }),
}; };
unsafe impl Sync for Mutex {}
impl Mutex { impl Mutex {
#[inline] #[inline]
pub unsafe fn new() -> Mutex { pub unsafe fn new() -> Mutex {

View File

@ -210,12 +210,13 @@ impl Clone for UnixStream {
// Unix Listener // Unix Listener
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[deriving(Sync)]
pub struct UnixListener { pub struct UnixListener {
inner: Inner, inner: Inner,
path: CString, path: CString,
} }
unsafe impl Sync for UnixListener {}
impl UnixListener { impl UnixListener {
pub fn bind(addr: &CString) -> IoResult<UnixListener> { pub fn bind(addr: &CString) -> IoResult<UnixListener> {
bind(addr, libc::SOCK_STREAM).map(|fd| { bind(addr, libc::SOCK_STREAM).map(|fd| {
@ -253,7 +254,6 @@ pub struct UnixAcceptor {
deadline: u64, deadline: u64,
} }
#[deriving(Sync)]
struct AcceptorInner { struct AcceptorInner {
listener: UnixListener, listener: UnixListener,
reader: FileDesc, reader: FileDesc,
@ -261,6 +261,8 @@ struct AcceptorInner {
closed: atomic::AtomicBool, closed: atomic::AtomicBool,
} }
unsafe impl Sync for AcceptorInner {}
impl UnixAcceptor { impl UnixAcceptor {
pub fn fd(&self) -> fd_t { self.inner.listener.fd() } pub fn fd(&self) -> fd_t { self.inner.listener.fd() }

View File

@ -29,11 +29,12 @@ pub use sys_common::net::TcpStream;
// TCP listeners // TCP listeners
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[deriving(Sync)]
pub struct TcpListener { pub struct TcpListener {
pub inner: FileDesc, pub inner: FileDesc,
} }
unsafe impl Sync for TcpListener {}
impl TcpListener { impl TcpListener {
pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> { pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
let fd = try!(net::socket(addr, libc::SOCK_STREAM)); let fd = try!(net::socket(addr, libc::SOCK_STREAM));
@ -90,7 +91,6 @@ pub struct TcpAcceptor {
deadline: u64, deadline: u64,
} }
#[deriving(Sync)]
struct AcceptorInner { struct AcceptorInner {
listener: TcpListener, listener: TcpListener,
reader: FileDesc, reader: FileDesc,
@ -98,6 +98,8 @@ struct AcceptorInner {
closed: atomic::AtomicBool, closed: atomic::AtomicBool,
} }
unsafe impl Sync for AcceptorInner {}
impl TcpAcceptor { impl TcpAcceptor {
pub fn fd(&self) -> sock_t { self.inner.listener.fd() } pub fn fd(&self) -> sock_t { self.inner.listener.fd() }

View File

@ -283,19 +283,22 @@ impl Builder {
} }
} }
#[deriving(Sync)]
struct Inner { struct Inner {
name: Option<String>, name: Option<String>,
lock: Mutex<bool>, // true when there is a buffered unpark lock: Mutex<bool>, // true when there is a buffered unpark
cvar: Condvar, cvar: Condvar,
} }
#[deriving(Clone, Sync)] unsafe impl Sync for Inner {}
#[deriving(Clone)]
/// A handle to a thread. /// A handle to a thread.
pub struct Thread { pub struct Thread {
inner: Arc<Inner>, inner: Arc<Inner>,
} }
unsafe impl Sync for Thread {}
impl Thread { impl Thread {
// Used only internally to construct a thread object without spawning // Used only internally to construct a thread object without spawning
fn new(name: Option<String>) -> Thread { fn new(name: Option<String>) -> Thread {

View File

@ -280,7 +280,7 @@ mod imp {
pub dtor_running: UnsafeCell<bool>, // should be Cell pub dtor_running: UnsafeCell<bool>, // should be Cell
} }
impl<T> ::kinds::Sync for Key<T> { } unsafe impl<T> ::kinds::Sync for Key<T> { }
#[doc(hidden)] #[doc(hidden)]
impl<T> Key<T> { impl<T> Key<T> {
@ -412,7 +412,7 @@ mod imp {
pub os: OsStaticKey, pub os: OsStaticKey,
} }
impl<T> ::kinds::Sync for Key<T> { } unsafe impl<T> ::kinds::Sync for Key<T> { }
struct Value<T: 'static> { struct Value<T: 'static> {
key: &'static Key<T>, key: &'static Key<T>,

View File

@ -202,7 +202,7 @@ mod imp {
#[doc(hidden)] #[doc(hidden)]
pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> } pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
#[cfg(not(stage0))] impl<T> ::kinds::Sync for KeyInner<T> { } unsafe impl<T> ::kinds::Sync for KeyInner<T> { }
#[doc(hidden)] #[doc(hidden)]
impl<T> KeyInner<T> { impl<T> KeyInner<T> {
@ -224,7 +224,7 @@ mod imp {
pub marker: marker::InvariantType<T>, pub marker: marker::InvariantType<T>,
} }
#[cfg(not(stage0))] impl<T> ::kinds::Sync for KeyInner<T> { } unsafe impl<T> ::kinds::Sync for KeyInner<T> { }
#[doc(hidden)] #[doc(hidden)]
impl<T> KeyInner<T> { impl<T> KeyInner<T> {

View File

@ -976,7 +976,7 @@ enum TestEvent {
pub type MonitorMsg = (TestDesc, TestResult, Vec<u8> ); pub type MonitorMsg = (TestDesc, TestResult, Vec<u8> );
impl Send for MonitorMsg {} unsafe impl Send for MonitorMsg {}
fn run_tests<F>(opts: &TestOpts, fn run_tests<F>(opts: &TestOpts,
tests: Vec<TestDescAndFn> , tests: Vec<TestDescAndFn> ,

View File

@ -18,7 +18,7 @@ struct Foo {
b: *const () b: *const ()
} }
impl Sync for Foo {} unsafe impl Sync for Foo {}
fn foo<T>(a: T) -> T { fn foo<T>(a: T) -> T {
a a

View File

@ -14,7 +14,7 @@ struct TestStruct {
x: *const u8 x: *const u8
} }
impl Sync for TestStruct {} unsafe impl Sync for TestStruct {}
static a: TestStruct = TestStruct{x: 0 as *const u8}; static a: TestStruct = TestStruct{x: 0 as *const u8};

View File

@ -14,7 +14,7 @@ struct TestStruct {
x: *const libc::c_void x: *const libc::c_void
} }
impl Sync for TestStruct {} unsafe impl Sync for TestStruct {}
extern fn foo() {} extern fn foo() {}
const x: extern "C" fn() = foo; const x: extern "C" fn() = foo;

View File

@ -12,7 +12,7 @@ struct TestStruct {
x: *const [int; 2] x: *const [int; 2]
} }
impl Sync for TestStruct {} unsafe impl Sync for TestStruct {}
static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [int; 2]}; static TEST_VALUE : TestStruct = TestStruct{x: 0x1234 as *const [int; 2]};

View File

@ -36,7 +36,7 @@ struct Wrap<T> {
value: T value: T
} }
impl<T: Send> Sync for Wrap<T> {} unsafe impl<T: Send> Sync for Wrap<T> {}
static UNSAFE: RacyCell<int> = RacyCell(UnsafeCell{value: 1}); static UNSAFE: RacyCell<int> = RacyCell(UnsafeCell{value: 1});
static WRAPPED_UNSAFE: Wrap<&'static RacyCell<int>> = Wrap { value: &UNSAFE }; static WRAPPED_UNSAFE: Wrap<&'static RacyCell<int>> = Wrap { value: &UNSAFE };

View File

@ -46,7 +46,7 @@ pub mod pipes {
payload: Option<T> payload: Option<T>
} }
impl<T:Send> Send for packet<T> {} unsafe impl<T:Send> Send for packet<T> {}
pub fn packet<T:Send>() -> *const packet<T> { pub fn packet<T:Send>() -> *const packet<T> {
unsafe { unsafe {

View File

@ -15,7 +15,7 @@ struct TestStruct {
x: *const int x: *const int
} }
impl Sync for TestStruct {} unsafe impl Sync for TestStruct {}
static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _}; static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _};