From f3a7ec7028c76b3a1c6051131328f372b068e33a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Dec 2014 15:03:01 -0800 Subject: std: Second pass stabilization of sync This pass performs a second pass of stabilization through the `std::sync` module, avoiding modules/types that are being handled in other PRs (e.g. mutexes, rwlocks, condvars, and channels). The following items are now stable * `sync::atomic` * `sync::atomic::ATOMIC_BOOL_INIT` (was `INIT_ATOMIC_BOOL`) * `sync::atomic::ATOMIC_INT_INIT` (was `INIT_ATOMIC_INT`) * `sync::atomic::ATOMIC_UINT_INIT` (was `INIT_ATOMIC_UINT`) * `sync::Once` * `sync::ONCE_INIT` * `sync::Once::call_once` (was `doit`) * C == `pthread_once(..)` * Boost == `call_once(..)` * Windows == `InitOnceExecuteOnce` * `sync::Barrier` * `sync::Barrier::new` * `sync::Barrier::wait` (now returns a `bool`) * `sync::Semaphore::new` * `sync::Semaphore::acquire` * `sync::Semaphore::release` The following items remain unstable * `sync::SemaphoreGuard` * `sync::Semaphore::access` - it's unclear how this relates to the poisoning story of mutexes. * `sync::TaskPool` - the semantics of a failing task and whether a thread is re-attached to a thread pool are somewhat unclear, and the utility of this type in `sync` is question with respect to the jobs of other primitives. This type will likely become stable or move out of the standard library over time. * `sync::Future` - futures as-is have yet to be deeply re-evaluated with the recent core changes to Rust's synchronization story, and will likely become stable in the future but are unstable until that time comes. [breaking-change] --- src/libstd/comm/blocking.rs | 4 +- src/libstd/io/buffered.rs | 6 -- src/libstd/io/stdio.rs | 2 +- src/libstd/io/tempfile.rs | 2 +- src/libstd/io/test.rs | 6 +- src/libstd/os.rs | 4 +- src/libstd/rand/os.rs | 6 +- src/libstd/rt/backtrace.rs | 2 +- src/libstd/rt/exclusive.rs | 119 ---------------------------------- src/libstd/rt/unwind.rs | 20 +++--- src/libstd/rt/util.rs | 2 +- src/libstd/sync/atomic.rs | 8 ++- src/libstd/sync/barrier.rs | 55 +++++++++++----- src/libstd/sync/condvar.rs | 2 +- src/libstd/sync/future.rs | 7 +- src/libstd/sync/mod.rs | 2 +- src/libstd/sync/once.rs | 33 ++++++---- src/libstd/sync/semaphore.rs | 3 + src/libstd/sync/task_pool.rs | 5 ++ src/libstd/sys/common/thread_local.rs | 2 +- src/libstd/sys/unix/os.rs | 2 +- src/libstd/sys/unix/pipe.rs | 10 +-- src/libstd/sys/unix/timer.rs | 2 +- src/libstd/sys/windows/mod.rs | 2 +- src/libstd/sys/windows/mutex.rs | 2 +- src/libstd/time/mod.rs | 2 +- 26 files changed, 113 insertions(+), 197 deletions(-) delete mode 100644 src/libstd/rt/exclusive.rs (limited to 'src/libstd') diff --git a/src/libstd/comm/blocking.rs b/src/libstd/comm/blocking.rs index 412b7161305..a5299012723 100644 --- a/src/libstd/comm/blocking.rs +++ b/src/libstd/comm/blocking.rs @@ -11,7 +11,7 @@ //! Generic support for building blocking abstractions. use thread::Thread; -use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering}; +use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sync::Arc; use kinds::{Sync, Send}; use kinds::marker::{NoSend, NoSync}; @@ -40,7 +40,7 @@ pub struct WaitToken { pub fn tokens() -> (WaitToken, SignalToken) { let inner = Arc::new(Inner { thread: Thread::current(), - woken: INIT_ATOMIC_BOOL, + woken: ATOMIC_BOOL_INIT, }); let wait_token = WaitToken { inner: inner.clone(), diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index c5405601048..aa05c65ce76 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -22,7 +22,6 @@ use result::Result::{Ok, Err}; use slice::{SliceExt}; use slice; use vec::Vec; -use kinds::{Send,Sync}; /// Wraps a Reader and buffers input from it /// @@ -52,11 +51,6 @@ pub struct BufferedReader { cap: uint, } - -unsafe impl Send for BufferedReader {} -unsafe impl Sync for BufferedReader {} - - impl BufferedReader { /// Creates a new `BufferedReader` with the specified buffer capacity pub fn with_capacity(cap: uint, inner: R) -> BufferedReader { diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index b7d069eb19e..c76d68a01be 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -218,7 +218,7 @@ pub fn stdin() -> StdinReader { static ONCE: Once = ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { // The default buffer capacity is 64k, but apparently windows doesn't like // 64k reads on stdin. See #13304 for details, but the idea is that on // windows we use a slightly smaller buffer that's been seen to be diff --git a/src/libstd/io/tempfile.rs b/src/libstd/io/tempfile.rs index c2b4d5a1fa9..5cf86676651 100644 --- a/src/libstd/io/tempfile.rs +++ b/src/libstd/io/tempfile.rs @@ -90,7 +90,7 @@ impl TempDir { return TempDir::new_in(&abs_tmpdir, suffix); } - static CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; let mut attempts = 0u; loop { diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 40941fda79c..3055359538b 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -16,17 +16,17 @@ use libc; use os; use prelude::*; use std::io::net::ip::*; -use sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Relaxed}; +use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Relaxed}; /// Get a port number, starting at 9600, for use in tests pub fn next_test_port() -> u16 { - static NEXT_OFFSET: AtomicUint = INIT_ATOMIC_UINT; + static NEXT_OFFSET: AtomicUint = ATOMIC_UINT_INIT; base_port() + NEXT_OFFSET.fetch_add(1, Relaxed) as u16 } /// Get a temporary path which could be the location of a unix socket pub fn next_test_unix() -> Path { - static COUNT: AtomicUint = INIT_ATOMIC_UINT; + static COUNT: AtomicUint = ATOMIC_UINT_INIT; // base port and pid are an attempt to be unique between multiple // test-runners of different configurations running on one // buildbot, the count is to be unique within this executable. diff --git a/src/libstd/os.rs b/src/libstd/os.rs index df50b7f81af..e470ee3cb4b 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -55,7 +55,7 @@ use slice::{AsSlice, SliceExt}; use slice::CloneSliceExt; use str::{Str, StrExt}; use string::{String, ToString}; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; +use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, SeqCst}; use vec::Vec; #[cfg(unix)] use c_str::ToCStr; @@ -596,7 +596,7 @@ pub fn last_os_error() -> String { error_string(errno() as uint) } -static EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT; +static EXIT_STATUS: AtomicInt = ATOMIC_INT_INIT; /// Sets the process exit code /// diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index ca36f2d8997..46b9fe9657c 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -84,10 +84,10 @@ mod imp { #[cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))] fn is_getrandom_available() -> bool { - use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed}; + use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Relaxed}; - static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL; - static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL; + static GETRANDOM_CHECKED: AtomicBool = ATOMIC_BOOL_INIT; + static GETRANDOM_AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT; if !GETRANDOM_CHECKED.load(Relaxed) { let mut buf: [u8; 0] = []; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 3eeb0ad3968..0b69486129a 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -22,7 +22,7 @@ pub use sys::backtrace::write; // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. pub fn log_enabled() -> bool { - static ENABLED: atomic::AtomicInt = atomic::INIT_ATOMIC_INT; + static ENABLED: atomic::AtomicInt = atomic::ATOMIC_INT_INIT; match ENABLED.load(atomic::SeqCst) { 1 => return false, 2 => return true, diff --git a/src/libstd/rt/exclusive.rs b/src/libstd/rt/exclusive.rs deleted file mode 100644 index 88bdb29caec..00000000000 --- a/src/libstd/rt/exclusive.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use core::prelude::*; - -use cell::UnsafeCell; -use rt::mutex; - -/// An OS mutex over some data. -/// -/// This is not a safe primitive to use, it is unaware of the libgreen -/// scheduler, as well as being easily susceptible to misuse due to the usage of -/// the inner NativeMutex. -/// -/// > **Note**: This type is not recommended for general use. The mutex provided -/// > as part of `libsync` should almost always be favored. -pub struct Exclusive { - lock: mutex::NativeMutex, - data: UnsafeCell, -} - -unsafe impl Send for Exclusive { } - -unsafe impl Sync for Exclusive { } - -/// An RAII guard returned via `lock` -pub struct ExclusiveGuard<'a, T:'a> { - // FIXME #12808: strange name to try to avoid interfering with - // field accesses of the contained type via Deref - _data: &'a mut T, - _guard: mutex::LockGuard<'a>, -} - -impl Exclusive { - /// Creates a new `Exclusive` which will protect the data provided. - pub fn new(user_data: T) -> Exclusive { - Exclusive { - lock: unsafe { mutex::NativeMutex::new() }, - data: UnsafeCell::new(user_data), - } - } - - /// Acquires this lock, returning a guard which the data is accessed through - /// and from which that lock will be unlocked. - /// - /// This method is unsafe due to many of the same reasons that the - /// NativeMutex itself is unsafe. - pub unsafe fn lock<'a>(&'a self) -> ExclusiveGuard<'a, T> { - let guard = self.lock.lock(); - let data = &mut *self.data.get(); - - ExclusiveGuard { - _data: data, - _guard: guard, - } - } -} - -impl<'a, T: Send> ExclusiveGuard<'a, T> { - // The unsafety here should be ok because our loan guarantees that the lock - // itself is not moving - pub fn signal(&self) { - unsafe { self._guard.signal() } - } - pub fn wait(&self) { - unsafe { self._guard.wait() } - } -} - -impl<'a, T: Send> Deref for ExclusiveGuard<'a, T> { - fn deref(&self) -> &T { &*self._data } -} -impl<'a, T: Send> DerefMut for ExclusiveGuard<'a, T> { - fn deref_mut(&mut self) -> &mut T { &mut *self._data } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use sync::Arc; - use super::Exclusive; - use task; - - #[test] - fn exclusive_new_arc() { - unsafe { - let mut futures = Vec::new(); - - let num_tasks = 10; - let count = 10; - - let total = Arc::new(Exclusive::new(box 0)); - - for _ in range(0u, num_tasks) { - let total = total.clone(); - let (tx, rx) = channel(); - futures.push(rx); - - task::spawn(move || { - for _ in range(0u, count) { - **total.lock() += 1; - } - tx.send(()); - }); - }; - - for f in futures.iter_mut() { f.recv() } - - assert_eq!(**total.lock(), num_tasks * count); - } - } -} diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index e0c512706e6..a6063d0b609 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -84,15 +84,15 @@ pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); // For more information, see below. const MAX_CALLBACKS: uint = 16; static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] = - [atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT, - atomic::INIT_ATOMIC_UINT, atomic::INIT_ATOMIC_UINT]; -static CALLBACK_CNT: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + [atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT, + atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT]; +static CALLBACK_CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; thread_local! { static PANICKING: Cell = Cell::new(false) } @@ -544,7 +544,7 @@ fn begin_unwind_inner(msg: Box, file_line: &(&'static str, uint)) -> // Make sure the default failure handler is registered before we look at the // callbacks. static INIT: Once = ONCE_INIT; - INIT.doit(|| unsafe { register(failure::on_fail); }); + INIT.call_once(|| unsafe { register(failure::on_fail); }); // First, invoke call the user-defined callbacks triggered on thread panic. // diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index fee86e33455..d66d8d52be9 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -47,7 +47,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { } pub fn min_stack() -> uint { - static MIN: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; match MIN.load(atomic::SeqCst) { 0 => {} n => return n - 1, diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index 18c917aca8a..71eae8ac8af 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -86,15 +86,15 @@ //! Keep a global count of live tasks: //! //! ``` -//! use std::sync::atomic::{AtomicUint, SeqCst, INIT_ATOMIC_UINT}; +//! use std::sync::atomic::{AtomicUint, SeqCst, ATOMIC_UINT_INIT}; //! -//! static GLOBAL_TASK_COUNT: AtomicUint = INIT_ATOMIC_UINT; +//! static GLOBAL_TASK_COUNT: AtomicUint = ATOMIC_UINT_INIT; //! //! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, SeqCst); //! println!("live tasks: {}", old_task_count + 1); //! ``` -#![allow(deprecated)] +#![stable] use alloc::boxed::Box; use core::mem; @@ -102,6 +102,7 @@ use core::prelude::{Send, Drop, None, Option, Some}; pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr}; pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT}; +pub use core::atomic::{ATOMIC_BOOL_INIT, ATOMIC_INT_INIT, ATOMIC_UINT_INIT}; pub use core::atomic::fence; pub use core::atomic::Ordering::{mod, Relaxed, Release, Acquire, AcqRel, SeqCst}; @@ -116,6 +117,7 @@ pub struct AtomicOption { p: AtomicUint, } +#[allow(deprecated)] impl AtomicOption { /// Create a new `AtomicOption` pub fn new(p: Box) -> AtomicOption { diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index 4091f0df395..6dc37cdadbe 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use kinds::{Send, Sync}; use sync::{Mutex, Condvar}; /// A barrier enables multiple tasks to synchronize the beginning @@ -30,29 +29,32 @@ use sync::{Mutex, Condvar}; /// }).detach(); /// } /// ``` +#[stable] pub struct Barrier { lock: Mutex, cvar: Condvar, num_threads: uint, } -unsafe impl Send for Barrier {} -unsafe impl Sync for Barrier {} - // The inner state of a double barrier struct BarrierState { count: uint, generation_id: uint, } -unsafe impl Send for BarrierState {} -unsafe impl Sync for BarrierState {} +/// A result returned from wait. +/// +/// Currently this opaque structure only has one method, `.is_leader()`. Only +/// one thread will receive a result that will return `true` from this function. +#[allow(missing_copy_implementations)] +pub struct BarrierWaitResult(bool); impl Barrier { /// Create a new barrier that can block a given number of threads. /// /// A barrier will block `n`-1 threads which call `wait` and then wake up /// all threads at once when the `n`th thread calls `wait`. + #[stable] pub fn new(n: uint) -> Barrier { Barrier { lock: Mutex::new(BarrierState { @@ -68,7 +70,13 @@ impl Barrier { /// /// Barriers are re-usable after all threads have rendezvoused once, and can /// be used continuously. - pub fn wait(&self) { + /// + /// A single (arbitrary) thread will receive a `BarrierWaitResult` that + /// returns `true` from `is_leader` when returning from this function, and + /// all other threads will receive a result that will return `false` from + /// `is_leader` + #[stable] + pub fn wait(&self) -> BarrierWaitResult { let mut lock = self.lock.lock().unwrap(); let local_gen = lock.generation_id; lock.count += 1; @@ -79,32 +87,44 @@ impl Barrier { lock.count < self.num_threads { lock = self.cvar.wait(lock).unwrap(); } + BarrierWaitResult(false) } else { lock.count = 0; lock.generation_id += 1; self.cvar.notify_all(); + BarrierWaitResult(true) } } } +impl BarrierWaitResult { + /// Return whether this thread from `wait` is the "leader thread". + /// + /// Only one thread will have `true` returned from their result, all other + /// threads will have `false` returned. + #[stable] + pub fn is_leader(&self) -> bool { self.0 } +} + #[cfg(test)] mod tests { use prelude::*; - use sync::{Arc, Barrier}; use comm::Empty; + use sync::{Arc, Barrier}; #[test] fn test_barrier() { - let barrier = Arc::new(Barrier::new(10)); + const N: uint = 10; + + let barrier = Arc::new(Barrier::new(N)); let (tx, rx) = channel(); - for _ in range(0u, 9) { + for _ in range(0u, N - 1) { let c = barrier.clone(); let tx = tx.clone(); spawn(move|| { - c.wait(); - tx.send(true); + tx.send(c.wait().is_leader()); }); } @@ -115,10 +135,15 @@ mod tests { _ => false, }); - barrier.wait(); + let mut leader_found = barrier.wait().is_leader(); + // Now, the barrier is cleared and we should get data. - for _ in range(0u, 9) { - rx.recv(); + for _ in range(0u, N - 1) { + if rx.recv() { + assert!(!leader_found); + leader_found = true; + } } + assert!(leader_found); } } diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 15faf5be258..79a7af7454d 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -88,7 +88,7 @@ unsafe impl Sync for StaticCondvar {} #[unstable = "may be merged with Condvar in the future"] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar { inner: sys::CONDVAR_INIT, - mutex: atomic::INIT_ATOMIC_UINT, + mutex: atomic::ATOMIC_UINT_INIT, }; impl Condvar { diff --git a/src/libstd/sync/future.rs b/src/libstd/sync/future.rs index 51899a87a32..c952d13ef04 100644 --- a/src/libstd/sync/future.rs +++ b/src/libstd/sync/future.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A type representing values that may be computed concurrently and operations for working with -//! them. +//! A type representing values that may be computed concurrently and operations +//! for working with them. //! //! # Example //! @@ -23,6 +23,9 @@ //! ``` #![allow(missing_docs)] +#![unstable = "futures as-is have yet to be deeply reevaluated with recent \ + core changes to Rust's synchronization story, and will likely \ + become stable in the future but are unstable until that time"] use core::prelude::*; use core::mem::replace; diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 092acc7ff25..de455d8a6c6 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -26,7 +26,7 @@ pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT}; pub use self::once::{Once, ONCE_INIT}; pub use self::semaphore::{Semaphore, SemaphoreGuard}; -pub use self::barrier::Barrier; +pub use self::barrier::{Barrier, BarrierWaitResult}; pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 4d9fbb59908..e9e3e79812a 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -32,10 +32,11 @@ use sync::{StaticMutex, MUTEX_INIT}; /// /// static START: Once = ONCE_INIT; /// -/// START.doit(|| { +/// START.call_once(|| { /// // run initialization here /// }); /// ``` +#[stable] pub struct Once { mutex: StaticMutex, cnt: atomic::AtomicInt, @@ -45,23 +46,25 @@ pub struct Once { unsafe impl Sync for Once {} /// Initialization value for static `Once` values. +#[stable] pub const ONCE_INIT: Once = Once { mutex: MUTEX_INIT, - cnt: atomic::INIT_ATOMIC_INT, - lock_cnt: atomic::INIT_ATOMIC_INT, + cnt: atomic::ATOMIC_INT_INIT, + lock_cnt: atomic::ATOMIC_INT_INIT, }; impl Once { /// Perform an initialization routine once and only once. The given closure - /// will be executed if this is the first time `doit` has been called, and - /// otherwise the routine will *not* be invoked. + /// will be executed if this is the first time `call_once` has been called, + /// and otherwise the routine will *not* be invoked. /// /// This method will block the calling task if another initialization /// routine is currently running. /// /// When this function returns, it is guaranteed that some initialization /// has run and completed (it may not be the closure specified). - pub fn doit(&'static self, f: F) where F: FnOnce() { + #[stable] + pub fn call_once(&'static self, f: F) where F: FnOnce() { // Optimize common path: load is much cheaper than fetch_add. if self.cnt.load(atomic::SeqCst) < 0 { return @@ -91,13 +94,13 @@ impl Once { // // It is crucial that the negative value is swapped in *after* the // initialization routine has completed because otherwise new threads - // calling `doit` will return immediately before the initialization has - // completed. + // calling `call_once` will return immediately before the initialization + // has completed. let prev = self.cnt.fetch_add(1, atomic::SeqCst); if prev < 0 { // Make sure we never overflow, we'll never have int::MIN - // simultaneous calls to `doit` to make this value go back to 0 + // simultaneous calls to `call_once` to make this value go back to 0 self.cnt.store(int::MIN, atomic::SeqCst); return } @@ -118,6 +121,10 @@ impl Once { unsafe { self.mutex.destroy() } } } + + /// Deprecated + #[deprecated = "renamed to `call_once`"] + pub fn doit(&'static self, f: F) where F: FnOnce() { self.call_once(f) } } #[cfg(test)] @@ -131,9 +138,9 @@ mod test { fn smoke_once() { static O: Once = ONCE_INIT; let mut a = 0i; - O.doit(|| a += 1); + O.call_once(|| a += 1); assert_eq!(a, 1); - O.doit(|| a += 1); + O.call_once(|| a += 1); assert_eq!(a, 1); } @@ -148,7 +155,7 @@ mod test { spawn(move|| { for _ in range(0u, 4) { Thread::yield_now() } unsafe { - O.doit(|| { + O.call_once(|| { assert!(!run); run = true; }); @@ -159,7 +166,7 @@ mod test { } unsafe { - O.doit(|| { + O.call_once(|| { assert!(!run); run = true; }); diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index e3b683a6ccb..bd86e5d0ed2 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![unstable = "the interaction between semaphores and the acquisition/release \ + of resources is currently unclear"] + use ops::Drop; use sync::{Mutex, Condvar}; diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index ee534f6cdde..632ad49e952 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -10,6 +10,11 @@ //! Abstraction of a thread pool for basic parallelism. +#![unstable = "the semantics of a failing task and whether a thread is \ + re-attached to a thread pool are somewhat unclear, and the \ + utility of this type in `std::sync` is questionable with \ + respect to the jobs of other primitives"] + use core::prelude::*; use thread::Thread; diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs index fe7a7d8d037..597790af83c 100644 --- a/src/libstd/sys/common/thread_local.rs +++ b/src/libstd/sys/common/thread_local.rs @@ -137,7 +137,7 @@ pub const INIT: StaticKey = StaticKey { /// /// This value allows specific configuration of the destructor for a TLS key. pub const INIT_INNER: StaticKeyInner = StaticKeyInner { - key: atomic::INIT_ATOMIC_UINT, + key: atomic::ATOMIC_UINT_INIT, }; static INIT_KEYS: Once = ONCE_INIT; diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 595191db3b2..0ccf130af6e 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -18,7 +18,7 @@ use io::{IoError, IoResult}; use libc::{mod, c_int, c_char, c_void}; use path::BytesContainer; use ptr; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; +use sync::atomic::{AtomicInt, SeqCst}; use sys::fs::FileDesc; use os; diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 868b460aa5e..1e1b95ee96c 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::*; + use alloc::arc::Arc; use libc; use c_str::CString; use mem; use sync::{atomic, Mutex}; use io::{mod, IoResult, IoError}; -use prelude::*; use sys::{mod, timer, retry, c, set_nonblocking, wouldblock}; use sys::fs::{fd_t, FileDesc}; @@ -117,9 +118,6 @@ pub struct UnixStream { write_deadline: u64, } -unsafe impl Send for UnixStream {} -unsafe impl Sync for UnixStream {} - impl UnixStream { pub fn connect(addr: &CString, timeout: Option) -> IoResult { @@ -218,6 +216,7 @@ pub struct UnixListener { path: CString, } +// we currently own the CString, so these impls should be safe unsafe impl Send for UnixListener {} unsafe impl Sync for UnixListener {} @@ -265,9 +264,6 @@ struct AcceptorInner { closed: atomic::AtomicBool, } -unsafe impl Send for AcceptorInner {} -unsafe impl Sync for AcceptorInner {} - impl UnixAcceptor { pub fn fd(&self) -> fd_t { self.inner.listener.fd() } diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index c0ef89666c0..25216c35b65 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -211,7 +211,7 @@ impl Timer { // instead of () HELPER.boot(|| {}, helper); - static ID: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; + static ID: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; let id = ID.fetch_add(1, atomic::Relaxed); Ok(Timer { id: id, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 57c284ed6a3..88313d66173 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -171,7 +171,7 @@ pub fn init_net() { unsafe { static START: Once = ONCE_INIT; - START.doit(|| { + START.call_once(|| { let mut data: c::WSADATA = mem::zeroed(); let ret = c::WSAStartup(0x202, // version 2.2 &mut data); diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs index 3ac7c09154e..5f65b429d86 100644 --- a/src/libstd/sys/windows/mutex.rs +++ b/src/libstd/sys/windows/mutex.rs @@ -20,7 +20,7 @@ const SPIN_COUNT: DWORD = 4000; pub struct Mutex { inner: atomic::AtomicUint } -pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::INIT_ATOMIC_UINT }; +pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::ATOMIC_UINT_INIT }; unsafe impl Sync for Mutex {} diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index 7bc15798a4f..d6c94f27a8b 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -45,7 +45,7 @@ fn precise_time_ns() -> u64 { denom: 0 }; static ONCE: sync::Once = sync::ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { imp::mach_timebase_info(&mut TIMEBASE); }); let time = imp::mach_absolute_time(); -- cgit 1.4.1-3-g733a5