From f3a7ec7028c76b3a1c6051131328f372b068e33a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 29 Dec 2014 15:03:01 -0800 Subject: [PATCH] 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/doc/guide-tasks.md | 2 + src/doc/guide.md | 1 + src/doc/reference.md | 4 +- src/libcollections/vec.rs | 2 +- src/libcore/atomic.rs | 16 ++- src/libcore/cell.rs | 2 + src/libcoretest/atomic.rs | 6 +- src/liblog/lib.rs | 2 +- .../middle/infer/region_inference/graphviz.rs | 2 +- src/librustc_trans/back/write.rs | 2 +- src/librustc_trans/trans/base.rs | 2 +- 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 +- src/libtime/lib.rs | 2 +- src/test/auxiliary/issue-17718.rs | 4 +- src/test/bench/shootout-binarytrees.rs | 10 +- src/test/bench/shootout-fannkuch-redux.rs | 8 +- .../compile-fail/std-uncopyable-atomics.rs | 6 +- src/test/run-pass/issue-17718.rs | 4 +- src/test/run-pass/vector-sort-panic-safe.rs | 20 +-- 44 files changed, 168 insertions(+), 237 deletions(-) delete mode 100644 src/libstd/rt/exclusive.rs diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md index 29c98e22ee9..8eb13187e58 100644 --- a/src/doc/guide-tasks.md +++ b/src/doc/guide-tasks.md @@ -206,6 +206,7 @@ getting the result later. The basic example below illustrates this. ```{rust,ignore} +# #![allow(deprecated)] use std::sync::Future; # fn main() { @@ -233,6 +234,7 @@ Here is another example showing how futures allow you to background computations. The workload will be distributed on the available cores. ```{rust,ignore} +# #![allow(deprecated)] # use std::num::Float; # use std::sync::Future; fn partial_sum(start: uint) -> f64 { diff --git a/src/doc/guide.md b/src/doc/guide.md index f4ec787a794..552ac31d038 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -5312,6 +5312,7 @@ example, if you wish to compute some value in the background, `Future` is a useful thing to use: ```{rust} +# #![allow(deprecated)] use std::sync::Future; let mut delayed_value = Future::spawn(move || { diff --git a/src/doc/reference.md b/src/doc/reference.md index f3ad19bbd2a..0ce7c30d197 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -1480,9 +1480,9 @@ data are being stored, or single-address and mutability properties are required. ``` use std::sync::atomic; -// Note that INIT_ATOMIC_UINT is a *const*, but it may be used to initialize a +// Note that ATOMIC_UINT_INIT is a *const*, but it may be used to initialize a // static. This static can be modified, so it is not placed in read-only memory. -static COUNTER: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +static COUNTER: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; // This table is a candidate to be placed in read-only memory. static TABLE: &'static [uint] = &[1, 2, 3, /* ... */]; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a1952352bad..02a627c42ac 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -2263,7 +2263,7 @@ mod tests { } } const NUM_ELEMENTS: uint = 2; - static DROP_COUNTER: AtomicUint = atomic::INIT_ATOMIC_UINT; + static DROP_COUNTER: AtomicUint = atomic::ATOMIC_UINT_INIT; let v = Vec::from_elem(NUM_ELEMENTS, Nothing); diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 6a40915f4dd..f653998c9bf 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -89,17 +89,27 @@ pub enum Ordering { /// An `AtomicBool` initialized to `false`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_BOOL: AtomicBool = +pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool { v: UnsafeCell { value: 0 } }; /// An `AtomicInt` initialized to `0`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_INT: AtomicInt = +pub const ATOMIC_INT_INIT: AtomicInt = AtomicInt { v: UnsafeCell { value: 0 } }; /// An `AtomicUint` initialized to `0`. #[unstable = "may be renamed, pending conventions for static initalizers"] -pub const INIT_ATOMIC_UINT: AtomicUint = +pub const ATOMIC_UINT_INIT: AtomicUint = AtomicUint { v: UnsafeCell { value: 0, } }; +/// Deprecated +#[deprecated = "renamed to ATOMIC_BOOL_INIT"] +pub const INIT_ATOMIC_BOOL: AtomicBool = ATOMIC_BOOL_INIT; +/// Deprecated +#[deprecated = "renamed to ATOMIC_INT_INIT"] +pub const INIT_ATOMIC_INT: AtomicInt = ATOMIC_INT_INIT; +/// Deprecated +#[deprecated = "renamed to ATOMIC_UINT_INIT"] +pub const INIT_ATOMIC_UINT: AtomicUint = ATOMIC_UINT_INIT; + // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly const UINT_TRUE: uint = -1; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 4b246860006..94e9441abc8 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -155,6 +155,8 @@ // FIXME: Can't be shared between threads. Dynamic borrows // FIXME: Relationship to Atomic types and RWLock +#![stable] + use clone::Clone; use cmp::PartialEq; use default::Default; diff --git a/src/libcoretest/atomic.rs b/src/libcoretest/atomic.rs index 1fee304a976..f8e943ec9f6 100644 --- a/src/libcoretest/atomic.rs +++ b/src/libcoretest/atomic.rs @@ -70,9 +70,9 @@ fn int_xor() { assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f); } -static S_BOOL : AtomicBool = INIT_ATOMIC_BOOL; -static S_INT : AtomicInt = INIT_ATOMIC_INT; -static S_UINT : AtomicUint = INIT_ATOMIC_UINT; +static S_BOOL : AtomicBool = ATOMIC_BOOL_INIT; +static S_INT : AtomicInt = ATOMIC_INT_INIT; +static S_UINT : AtomicUint = ATOMIC_UINT_INIT; #[test] fn static_init() { diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index b30938ae7f5..4ee5b2d5e83 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -352,7 +352,7 @@ pub struct LogLocation { #[doc(hidden)] pub fn mod_enabled(level: u32, module: &str) -> bool { static INIT: Once = ONCE_INIT; - INIT.doit(init); + INIT.call_once(init); // It's possible for many threads are in this function, only one of them // will perform the global initialization, but all of them will need to check diff --git a/src/librustc/middle/infer/region_inference/graphviz.rs b/src/librustc/middle/infer/region_inference/graphviz.rs index 8455ee3955b..b6020fe5ce3 100644 --- a/src/librustc/middle/infer/region_inference/graphviz.rs +++ b/src/librustc/middle/infer/region_inference/graphviz.rs @@ -73,7 +73,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, let output_path = { let output_template = match requested_output { Some(ref s) if s.as_slice() == "help" => { - static PRINTED_YET : atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL; + static PRINTED_YET : atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT; if !PRINTED_YET.load(atomic::SeqCst) { print_help_message(); PRINTED_YET.store(true, atomic::SeqCst); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index a6f2c7dfed0..f2242b72aae 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1009,7 +1009,7 @@ unsafe fn configure_llvm(sess: &Session) { } } - INIT.doit(|| { + INIT.call_once(|| { llvm::LLVMInitializePasses(); // Only initialize the platforms supported by Rust here, because diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 47544365426..18a3ce2ab72 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -3097,7 +3097,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) use std::sync::{Once, ONCE_INIT}; static INIT: Once = ONCE_INIT; static mut POISONED: bool = false; - INIT.doit(|| { + INIT.call_once(|| { if llvm::LLVMStartMultithreaded() != 1 { // use an extra bool to make sure that all future usage of LLVM // cannot proceed despite the Once not running more than once. 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(); diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 87a00334c47..2cf4c156069 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -198,7 +198,7 @@ pub fn precise_time_ns() -> u64 { denom: 0 }; static ONCE: std::sync::Once = std::sync::ONCE_INIT; unsafe { - ONCE.doit(|| { + ONCE.call_once(|| { imp::mach_timebase_info(&mut TIMEBASE); }); let time = imp::mach_absolute_time(); diff --git a/src/test/auxiliary/issue-17718.rs b/src/test/auxiliary/issue-17718.rs index f0b431b1db9..689610d799e 100644 --- a/src/test/auxiliary/issue-17718.rs +++ b/src/test/auxiliary/issue-17718.rs @@ -11,12 +11,12 @@ use std::sync::atomic; pub const C1: uint = 1; -pub const C2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +pub const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; pub const C3: fn() = foo; pub const C4: uint = C1 * C1 + C1 / C1; pub const C5: &'static uint = &C4; pub static S1: uint = 3; -pub static S2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +pub static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; fn foo() {} diff --git a/src/test/bench/shootout-binarytrees.rs b/src/test/bench/shootout-binarytrees.rs index 0b16e8011e8..236e1cbb217 100644 --- a/src/test/bench/shootout-binarytrees.rs +++ b/src/test/bench/shootout-binarytrees.rs @@ -41,7 +41,7 @@ extern crate arena; use std::iter::range_step; -use std::sync::Future; +use std::thread::Thread; use arena::TypedArena; enum Tree<'a> { @@ -95,7 +95,7 @@ fn main() { let mut messages = range_step(min_depth, max_depth + 1, 2).map(|depth| { use std::num::Int; let iterations = 2i.pow((max_depth - depth + min_depth) as uint); - Future::spawn(move|| { + Thread::spawn(move|| { let mut chk = 0; for i in range(1, iterations + 1) { let arena = TypedArena::new(); @@ -106,10 +106,10 @@ fn main() { format!("{}\t trees of depth {}\t check: {}", iterations * 2, depth, chk) }) - }).collect::>>(); + }).collect::>(); - for message in messages.iter_mut() { - println!("{}", *message.get_ref()); + for message in messages.into_iter() { + println!("{}", message.join().ok().unwrap()); } println!("long lived tree of depth {}\t check: {}", diff --git a/src/test/bench/shootout-fannkuch-redux.rs b/src/test/bench/shootout-fannkuch-redux.rs index ef38f5ef743..8e594b86180 100644 --- a/src/test/bench/shootout-fannkuch-redux.rs +++ b/src/test/bench/shootout-fannkuch-redux.rs @@ -41,7 +41,7 @@ #![feature(slicing_syntax)] use std::{cmp, iter, mem}; -use std::sync::Future; +use std::thread::Thread; fn rotate(x: &mut [i32]) { let mut prev = x[0]; @@ -168,15 +168,15 @@ fn fannkuch(n: i32) -> (i32, i32) { for (i, j) in range(0, N).zip(iter::count(0, k)) { let max = cmp::min(j+k, perm.max()); - futures.push(Future::spawn(move|| { + futures.push(Thread::spawn(move|| { work(perm, j as uint, max as uint) })) } let mut checksum = 0; let mut maxflips = 0; - for fut in futures.iter_mut() { - let (cs, mf) = fut.get(); + for fut in futures.into_iter() { + let (cs, mf) = fut.join().ok().unwrap(); checksum += cs; maxflips = cmp::max(maxflips, mf); } diff --git a/src/test/compile-fail/std-uncopyable-atomics.rs b/src/test/compile-fail/std-uncopyable-atomics.rs index c0122b8a2a9..501187ca9e5 100644 --- a/src/test/compile-fail/std-uncopyable-atomics.rs +++ b/src/test/compile-fail/std-uncopyable-atomics.rs @@ -16,11 +16,11 @@ use std::sync::atomic::*; use std::ptr; fn main() { - let x = INIT_ATOMIC_BOOL; + let x = ATOMIC_BOOL_INIT; let x = *&x; //~ ERROR: cannot move out of dereference - let x = INIT_ATOMIC_INT; + let x = ATOMIC_INT_INIT; let x = *&x; //~ ERROR: cannot move out of dereference - let x = INIT_ATOMIC_UINT; + let x = ATOMIC_UINT_INIT; let x = *&x; //~ ERROR: cannot move out of dereference let x: AtomicPtr = AtomicPtr::new(ptr::null_mut()); let x = *&x; //~ ERROR: cannot move out of dereference diff --git a/src/test/run-pass/issue-17718.rs b/src/test/run-pass/issue-17718.rs index 90a102222ba..10ad0f620e9 100644 --- a/src/test/run-pass/issue-17718.rs +++ b/src/test/run-pass/issue-17718.rs @@ -15,7 +15,7 @@ extern crate "issue-17718" as other; use std::sync::atomic; const C1: uint = 1; -const C2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; const C3: fn() = foo; const C4: uint = C1 * C1 + C1 / C1; const C5: &'static uint = &C4; @@ -25,7 +25,7 @@ const C6: uint = { }; static S1: uint = 3; -static S2: atomic::AtomicUint = atomic::INIT_ATOMIC_UINT; +static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT; mod test { static A: uint = 4; diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs index 6ff1cffb4a4..c5f5cd2c3aa 100644 --- a/src/test/run-pass/vector-sort-panic-safe.rs +++ b/src/test/run-pass/vector-sort-panic-safe.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::task; -use std::sync::atomic::{AtomicUint, INIT_ATOMIC_UINT, Relaxed}; +use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Relaxed}; use std::rand::{thread_rng, Rng, Rand}; const REPEATS: uint = 5; @@ -17,18 +17,18 @@ const MAX_LEN: uint = 32; static drop_counts: [AtomicUint; MAX_LEN] = // FIXME #5244: AtomicUint is not Copy. [ - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, - INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, + ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ]; -static creation_count: AtomicUint = INIT_ATOMIC_UINT; +static creation_count: AtomicUint = ATOMIC_UINT_INIT; #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)] struct DropCounter { x: uint, creation_id: uint }