diff options
Diffstat (limited to 'src/libstd')
85 files changed, 1216 insertions, 1176 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index db01c091dc0..857a7072009 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -234,7 +234,7 @@ pub fn escape_default<F>(c: u8, mut f: F) where } } -static ASCII_LOWERCASE_MAP: [u8, ..256] = [ +static ASCII_LOWERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, @@ -273,7 +273,7 @@ static ASCII_LOWERCASE_MAP: [u8, ..256] = [ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, ]; -static ASCII_UPPERCASE_MAP: [u8, ..256] = [ +static ASCII_UPPERCASE_MAP: [u8; 256] = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, diff --git a/src/libstd/bitflags.rs b/src/libstd/bitflags.rs index 4ec329de600..c07531d3f32 100644 --- a/src/libstd/bitflags.rs +++ b/src/libstd/bitflags.rs @@ -104,6 +104,10 @@ /// - `empty`: an empty set of flags /// - `all`: the set of all flags /// - `bits`: the raw value of the flags currently stored +/// - `from_bits`: convert from underlying bit representation, unless that +/// representation contains bits that do not correspond to a flag +/// - `from_bits_truncate`: convert from underlying bit representation, dropping +/// any bits that do not correspond to flags /// - `is_empty`: `true` if no flags are currently stored /// - `is_all`: `true` if all flags are currently set /// - `intersects`: `true` if there are flags common to both `self` and `other` @@ -237,17 +241,6 @@ macro_rules! bitflags { } } - // NOTE(stage0): Remove impl after a snapshot - #[cfg(stage0)] - impl ::std::ops::Not<$BitFlags> for $BitFlags { - /// Returns the complement of this set of flags. - #[inline] - fn not(&self) -> $BitFlags { - $BitFlags { bits: !self.bits } & $BitFlags::all() - } - } - - #[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot impl ::std::ops::Not<$BitFlags> for $BitFlags { /// Returns the complement of this set of flags. #[inline] diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index d096903f9c4..33cf33848f0 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -77,7 +77,7 @@ use fmt; use hash; use mem; use ptr; -use slice::{mod, ImmutableIntSlice}; +use slice::{mod, IntSliceExt}; use str; use string::String; use core::kinds::marker; @@ -465,7 +465,7 @@ unsafe fn with_c_str<T, F>(v: &[u8], checked: bool, f: F) -> T where F: FnOnce(*const libc::c_char) -> T, { let c_str = if v.len() < BUF_LEN { - let mut buf: [u8, .. BUF_LEN] = mem::uninitialized(); + let mut buf: [u8; BUF_LEN] = mem::uninitialized(); slice::bytes::copy_memory(&mut buf, v); buf[v.len()] = 0; @@ -497,6 +497,8 @@ fn check_for_null(v: &[u8], buf: *mut libc::c_char) { /// External iterator for a CString's bytes. /// /// Use with the `std::iter` module. +#[allow(raw_pointer_deriving)] +#[deriving(Clone)] pub struct CChars<'a> { ptr: *const libc::c_char, marker: marker::ContravariantLifetime<'a>, diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs index a80659ed937..40942f1b987 100644 --- a/src/libstd/c_vec.rs +++ b/src/libstd/c_vec.rs @@ -40,7 +40,7 @@ use mem; use ops::{Drop, FnOnce}; use option::Option; use option::Option::{Some, None}; -use ptr::RawPtr; +use ptr::PtrExt; use ptr; use raw; use slice::AsSlice; diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 8585b4ecf52..4738c830bd3 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -264,30 +264,39 @@ fn test_resize_policy() { /// } /// ``` /// -/// The easiest way to use `HashMap` with a custom type is to derive `Eq` and `Hash`. +/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`. /// We must also derive `PartialEq`. /// /// ``` /// use std::collections::HashMap; /// /// #[deriving(Hash, Eq, PartialEq, Show)] -/// struct Viking<'a> { -/// name: &'a str, -/// power: uint, +/// struct Viking { +/// name: String, +/// country: String, /// } /// +/// impl Viking { +/// /// Create a new Viking. +/// fn new(name: &str, country: &str) -> Viking { +/// Viking { name: name.to_string(), country: country.to_string() } +/// } +/// } +/// +/// // Use a HashMap to store the vikings' health points. /// let mut vikings = HashMap::new(); /// -/// vikings.insert("Norway", Viking { name: "Einar", power: 9u }); -/// vikings.insert("Denmark", Viking { name: "Olaf", power: 4u }); -/// vikings.insert("Iceland", Viking { name: "Harald", power: 8u }); +/// vikings.insert(Viking::new("Einar", "Norway"), 25u); +/// vikings.insert(Viking::new("Olaf", "Denmark"), 24u); +/// vikings.insert(Viking::new("Harald", "Iceland"), 12u); /// -/// // Use derived implementation to print the vikings. -/// for (land, viking) in vikings.iter() { -/// println!("{} at {}", viking, land); +/// // Use derived implementation to print the status of the vikings. +/// for (viking, health) in vikings.iter() { +/// println!("{} has {} hp", viking, health); /// } /// ``` #[deriving(Clone)] +#[stable] pub struct HashMap<K, V, H = RandomSipHasher> { // All hashes are keyed on these values, to prevent hash collision attacks. hasher: H, @@ -500,7 +509,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> { /// let mut map: HashMap<&str, int> = HashMap::new(); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn new() -> HashMap<K, V, RandomSipHasher> { let hasher = RandomSipHasher::new(); HashMap::with_hasher(hasher) @@ -515,7 +524,7 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> { /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> { let hasher = RandomSipHasher::new(); HashMap::with_capacity_and_hasher(capacity, hasher) @@ -538,6 +547,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// map.insert(1i, 2u); /// ``` #[inline] + #[unstable = "hasher stuff is unclear"] pub fn with_hasher(hasher: H) -> HashMap<K, V, H> { HashMap { hasher: hasher, @@ -565,6 +575,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// map.insert(1i, 2u); /// ``` #[inline] + #[unstable = "hasher stuff is unclear"] pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> { let resize_policy = DefaultResizePolicy::new(); let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity)); @@ -587,7 +598,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert!(map.capacity() >= 100); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn capacity(&self) -> uint { self.resize_policy.usable_capacity(self.table.capacity()) } @@ -607,7 +618,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// let mut map: HashMap<&str, int> = HashMap::new(); /// map.reserve(10); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn reserve(&mut self, additional: uint) { let new_size = self.len().checked_add(additional).expect("capacity overflow"); let min_cap = self.resize_policy.min_capacity(new_size); @@ -719,7 +730,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// map.shrink_to_fit(); /// assert!(map.capacity() >= 2); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn shrink_to_fit(&mut self) { let min_capacity = self.resize_policy.min_capacity(self.len()); let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY); @@ -837,7 +848,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// println!("{}", key); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn keys<'a>(&'a self) -> Keys<'a, K, V> { fn first<A, B>((a, _): (A, B)) -> A { a } let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr @@ -862,7 +873,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// println!("{}", key); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn values<'a>(&'a self) -> Values<'a, K, V> { fn second<A, B>((_, b): (A, B)) -> B { b } let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr @@ -887,9 +898,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// println!("key: {} val: {}", key, val); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn iter(&self) -> Entries<K, V> { - Entries { inner: self.table.iter() } + #[stable] + pub fn iter(&self) -> Iter<K, V> { + Iter { inner: self.table.iter() } } /// An iterator visiting all key-value pairs in arbitrary order, @@ -915,7 +926,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// println!("key: {} val: {}", key, val); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn iter_mut(&mut self) -> IterMut<K, V> { IterMut { inner: self.table.iter_mut() } } @@ -937,7 +948,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// // Not possible with .iter() /// let vec: Vec<(&str, int)> = map.into_iter().collect(); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn into_iter(self) -> IntoIter<K, V> { fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) } let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; @@ -968,7 +979,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// a.insert(1u, "a"); /// assert_eq!(a.len(), 1); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn len(&self) -> uint { self.table.size() } /// Return true if the map contains no elements. @@ -984,7 +995,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert!(!a.is_empty()); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Clears the map, returning all key-value pairs as an iterator. Keeps the @@ -1030,7 +1041,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// a.clear(); /// assert!(a.is_empty()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] #[inline] pub fn clear(&mut self) { self.drain(); @@ -1058,7 +1069,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert_eq!(map.get(&1), Some(&"a")); /// assert_eq!(map.get(&2), None); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V> where Q: Hash<S> + Eq + BorrowFrom<K> { @@ -1081,7 +1092,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn contains_key<Sized? Q>(&self, k: &Q) -> bool where Q: Hash<S> + Eq + BorrowFrom<K> { @@ -1113,7 +1124,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// } /// assert_eq!(map[1], "b"); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V> where Q: Hash<S> + Eq + BorrowFrom<K> { @@ -1142,7 +1153,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert_eq!(map.insert(37, "c"), Some("b")); /// assert_eq!(map[37], "c"); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn insert(&mut self, k: K, v: V) -> Option<V> { let hash = self.make_hash(&k); self.reserve(1); @@ -1177,7 +1188,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> { /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V> where Q: Hash<S> + Eq + BorrowFrom<K> { @@ -1253,6 +1264,7 @@ impl<K: Eq + Hash<S>, V: Clone, S, H: Hasher<S>> HashMap<K, V, H> { } } +#[stable] impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, H> { fn eq(&self, other: &HashMap<K, V, H>) -> bool { if self.len() != other.len() { return false; } @@ -1263,8 +1275,10 @@ impl<K: Eq + Hash<S>, V: PartialEq, S, H: Hasher<S>> PartialEq for HashMap<K, V, } } +#[stable] impl<K: Eq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {} +#[stable] impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); @@ -1286,6 +1300,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> } } +#[stable] impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V, H> where Q: BorrowFrom<K> + Hash<S> + Eq { @@ -1295,6 +1310,7 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V } } +#[stable] impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K, V, H> where Q: BorrowFrom<K> + Hash<S> + Eq { @@ -1305,16 +1321,28 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K } /// HashMap iterator -pub struct Entries<'a, K: 'a, V: 'a> { - inner: table::Entries<'a, K, V> +#[stable] +pub struct Iter<'a, K: 'a, V: 'a> { + inner: table::Iter<'a, K, V> +} + +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { + Iter { + inner: self.inner.clone() + } + } } /// HashMap mutable values iterator +#[stable] pub struct IterMut<'a, K: 'a, V: 'a> { inner: table::IterMut<'a, K, V> } /// HashMap move iterator +#[stable] pub struct IntoIter<K, V> { inner: iter::Map< (SafeHash, K, V), @@ -1325,16 +1353,37 @@ pub struct IntoIter<K, V> { } /// HashMap keys iterator +#[stable] pub struct Keys<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> + inner: Map<(&'a K, &'a V), &'a K, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K> +} + +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Keys<'a, K, V> { + fn clone(&self) -> Keys<'a, K, V> { + Keys { + inner: self.inner.clone() + } + } } /// HashMap values iterator +#[stable] pub struct Values<'a, K: 'a, V: 'a> { - inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> + inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V> +} + +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Values<'a, K, V> { + fn clone(&self) -> Values<'a, K, V> { + Values { + inner: self.inner.clone() + } + } } /// HashMap drain iterator +#[unstable = "matches collection reform specification, waiting for dust to settle"] pub struct Drain<'a, K: 'a, V: 'a> { inner: iter::Map< (SafeHash, K, V), @@ -1373,31 +1422,37 @@ enum VacantEntryState<K, V, M> { NoElem(EmptyBucket<K, V, M>), } -impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { +#[stable] +impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, V> { #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() } } +#[stable] impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for IterMut<'a, K, V> { #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() } } +#[stable] impl<K, V> Iterator<(K, V)> for IntoIter<K, V> { #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() } } +#[stable] impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> { #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() } } +#[stable] impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> { #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() } #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() } } +#[stable] impl<'a, K: 'a, V: 'a> Iterator<(K, V)> for Drain<'a, K, V> { #[inline] fn next(&mut self) -> Option<(K, V)> { @@ -1454,6 +1509,7 @@ impl<'a, K, V> VacantEntry<'a, K, V> { } } +#[stable] impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> { fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> { let lower = iter.size_hint().0; @@ -1463,6 +1519,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for Has } } +#[stable] impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Extend<(K, V)> for HashMap<K, V, H> { fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) { for (k, v) in iter { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index e00116344c8..6132d288da2 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -90,6 +90,7 @@ use super::map::{mod, HashMap, Keys, INITIAL_CAPACITY}; /// } /// ``` #[deriving(Clone)] +#[stable] pub struct HashSet<T, H = RandomSipHasher> { map: HashMap<T, (), H> } @@ -104,7 +105,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> { /// let mut set: HashSet<int> = HashSet::new(); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn new() -> HashSet<T, RandomSipHasher> { HashSet::with_capacity(INITIAL_CAPACITY) } @@ -119,7 +120,7 @@ impl<T: Hash + Eq> HashSet<T, RandomSipHasher> { /// let mut set: HashSet<int> = HashSet::with_capacity(10); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> { HashSet { map: HashMap::with_capacity(capacity) } } @@ -142,6 +143,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// set.insert(2u); /// ``` #[inline] + #[unstable = "hasher stuff is unclear"] pub fn with_hasher(hasher: H) -> HashSet<T, H> { HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher) } @@ -165,6 +167,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// set.insert(1i); /// ``` #[inline] + #[unstable = "hasher stuff is unclear"] pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> { HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) } } @@ -179,7 +182,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert!(set.capacity() >= 100); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn capacity(&self) -> uint { self.map.capacity() } @@ -199,7 +202,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// let mut set: HashSet<int> = HashSet::new(); /// set.reserve(10); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn reserve(&mut self, additional: uint) { self.map.reserve(additional) } @@ -220,7 +223,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// set.shrink_to_fit(); /// assert!(set.capacity() >= 2); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn shrink_to_fit(&mut self) { self.map.shrink_to_fit() } @@ -248,8 +251,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// println!("{}", x); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] - pub fn iter<'a>(&'a self) -> Iter<'a, T> { + #[stable] + pub fn iter(&self) -> Iter<T> { Iter { iter: self.map.keys() } } @@ -273,7 +276,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// println!("{}", x); /// } /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn into_iter(self) -> IntoIter<T> { fn first<A, B>((a, _): (A, B)) -> A { a } let first: fn((T, ())) -> T = first; @@ -303,7 +306,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect(); /// assert_eq!(diff, [4i].iter().map(|&x| x).collect()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> Difference<'a, T, H> { Difference { iter: self.iter(), @@ -331,7 +334,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert_eq!(diff1, diff2); /// assert_eq!(diff1, [1i, 4].iter().map(|&x| x).collect()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SymmetricDifference<'a, T, H> { SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) } @@ -354,7 +357,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect(); /// assert_eq!(diff, [2i, 3].iter().map(|&x| x).collect()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>) -> Intersection<'a, T, H> { Intersection { iter: self.iter(), @@ -379,7 +382,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect(); /// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> Union<'a, T, H> { Union { iter: self.iter().chain(other.difference(self)) } } @@ -396,7 +399,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// v.insert(1u); /// assert_eq!(v.len(), 1); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn len(&self) -> uint { self.map.len() } /// Returns true if the set contains no elements @@ -411,7 +414,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// v.insert(1u); /// assert!(!v.is_empty()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn is_empty(&self) -> bool { self.map.len() == 0 } /// Clears the set, returning all elements in an iterator. @@ -436,7 +439,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// v.clear(); /// assert!(v.is_empty()); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn clear(&mut self) { self.map.clear() } /// Returns `true` if the set contains a value. @@ -454,7 +457,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Hash<S> + Eq { @@ -478,7 +481,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// b.insert(1); /// assert_eq!(a.is_disjoint(&b), false); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn is_disjoint(&self, other: &HashSet<T, H>) -> bool { self.iter().all(|v| !other.contains(v)) } @@ -499,7 +502,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// set.insert(4); /// assert_eq!(set.is_subset(&sup), false); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn is_subset(&self, other: &HashSet<T, H>) -> bool { self.iter().all(|v| other.contains(v)) } @@ -524,7 +527,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert_eq!(set.is_superset(&sub), true); /// ``` #[inline] - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn is_superset(&self, other: &HashSet<T, H>) -> bool { other.is_subset(self) } @@ -543,7 +546,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert_eq!(set.insert(2), false); /// assert_eq!(set.len(), 1); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() } /// Removes a value from the set. Returns `true` if the value was @@ -564,7 +567,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` - #[unstable = "matches collection reform specification, waiting for dust to settle"] + #[stable] pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Hash<S> + Eq { @@ -572,6 +575,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> { } } +#[stable] impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { fn eq(&self, other: &HashSet<T, H>) -> bool { if self.len() != other.len() { return false; } @@ -580,8 +584,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { } } +#[stable] impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {} +#[stable] impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); @@ -595,6 +601,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> { } } +#[stable] impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> { fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> { let lower = iter.size_hint().0; @@ -604,6 +611,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, } } +#[stable] impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extend<T> for HashSet<T, H> { fn extend<I: Iterator<T>>(&mut self, mut iter: I) { for k in iter { @@ -620,7 +628,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> { } } -#[unstable = "matches collection reform specification, waiting for dust to settle"] +#[stable] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitOr<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { /// Returns the union of `self` and `rhs` as a new `HashSet<T, H>`. @@ -648,7 +656,7 @@ BitOr<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { } } -#[unstable = "matches collection reform specification, waiting for dust to settle"] +#[stable] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitAnd<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, H>`. @@ -676,7 +684,7 @@ BitAnd<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { } } -#[unstable = "matches collection reform specification, waiting for dust to settle"] +#[stable] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> BitXor<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, H>`. @@ -704,7 +712,7 @@ BitXor<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { } } -#[unstable = "matches collection reform specification, waiting for dust to settle"] +#[stable] impl<'a, 'b, T: Eq + Hash<S> + Clone, S, H: Hasher<S> + Default> Sub<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { /// Returns the difference of `self` and `rhs` as a new `HashSet<T, H>`. @@ -733,21 +741,25 @@ Sub<&'b HashSet<T, H>, HashSet<T, H>> for &'a HashSet<T, H> { } /// HashSet iterator +#[stable] pub struct Iter<'a, K: 'a> { iter: Keys<'a, K, ()> } /// HashSet move iterator +#[stable] pub struct IntoIter<K> { iter: Map<(K, ()), K, map::IntoIter<K, ()>, fn((K, ())) -> K> } /// HashSet drain iterator +#[stable] pub struct Drain<'a, K: 'a> { iter: Map<(K, ()), K, map::Drain<'a, K, ()>, fn((K, ())) -> K>, } /// Intersection iterator +#[stable] pub struct Intersection<'a, T: 'a, H: 'a> { // iterator of the first set iter: Iter<'a, T>, @@ -756,6 +768,7 @@ pub struct Intersection<'a, T: 'a, H: 'a> { } /// Difference iterator +#[stable] pub struct Difference<'a, T: 'a, H: 'a> { // iterator of the first set iter: Iter<'a, T>, @@ -764,30 +777,36 @@ pub struct Difference<'a, T: 'a, H: 'a> { } /// Symmetric difference iterator. +#[stable] pub struct SymmetricDifference<'a, T: 'a, H: 'a> { iter: Chain<Difference<'a, T, H>, Difference<'a, T, H>> } /// Set union iterator. +#[stable] pub struct Union<'a, T: 'a, H: 'a> { iter: Chain<Iter<'a, T>, Difference<'a, T, H>> } +#[stable] impl<'a, K> Iterator<&'a K> for Iter<'a, K> { fn next(&mut self) -> Option<&'a K> { self.iter.next() } fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() } } +#[stable] impl<K> Iterator<K> for IntoIter<K> { fn next(&mut self) -> Option<K> { self.iter.next() } fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() } } +#[stable] impl<'a, K: 'a> Iterator<K> for Drain<'a, K> { fn next(&mut self) -> Option<K> { self.iter.next() } fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() } } +#[stable] impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -808,6 +827,7 @@ impl<'a, T, S, H> Iterator<&'a T> for Intersection<'a, T, H> } } +#[stable] impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -828,6 +848,7 @@ impl<'a, T, S, H> Iterator<&'a T> for Difference<'a, T, H> } } +#[stable] impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { @@ -835,6 +856,7 @@ impl<'a, T, S, H> Iterator<&'a T> for SymmetricDifference<'a, T, H> fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() } } +#[stable] impl<'a, T, S, H> Iterator<&'a T> for Union<'a, T, H> where T: Eq + Hash<S>, H: Hasher<S> { diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 3ae3a8ffbad..6938ab9b0b6 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -23,7 +23,7 @@ use num::{Int, UnsignedInt}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{Some, None}; -use ptr::{Unique, RawPtr, copy_nonoverlapping_memory, zero_memory}; +use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory}; use ptr; use rt::heap::{allocate, deallocate}; @@ -657,8 +657,8 @@ impl<K, V> RawTable<K, V> { } } - pub fn iter(&self) -> Entries<K, V> { - Entries { + pub fn iter(&self) -> Iter<K, V> { + Iter { iter: self.raw_buckets(), elems_left: self.size(), } @@ -718,6 +718,18 @@ struct RawBuckets<'a, K, V> { marker: marker::ContravariantLifetime<'a>, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for RawBuckets<'a, K, V> { + fn clone(&self) -> RawBuckets<'a, K, V> { + RawBuckets { + raw: self.raw, + hashes_end: self.hashes_end, + marker: marker::ContravariantLifetime, + } + } +} + + impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> { fn next(&mut self) -> Option<RawBucket<K, V>> { while self.raw.hash != self.hashes_end { @@ -770,11 +782,22 @@ impl<'a, K, V> Iterator<(K, V)> for RevMoveBuckets<'a, K, V> { } /// Iterator over shared references to entries in a table. -pub struct Entries<'a, K: 'a, V: 'a> { +pub struct Iter<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, elems_left: uint, } +// FIXME(#19839) Remove in favor of `#[deriving(Clone)]` +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { + Iter { + iter: self.iter.clone(), + elems_left: self.elems_left + } + } +} + + /// Iterator over mutable references to entries in a table. pub struct IterMut<'a, K: 'a, V: 'a> { iter: RawBuckets<'a, K, V>, @@ -793,7 +816,7 @@ pub struct Drain<'a, K: 'a, V: 'a> { iter: RawBuckets<'static, K, V>, } -impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> { +impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, V> { fn next(&mut self) -> Option<(&'a K, &'a V)> { self.iter.next().map(|bucket| { self.elems_left -= 1; diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 956185c6443..32e1922ae74 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -81,6 +81,7 @@ use prelude::v1::*; use str::Utf8Error; +use string::{FromUtf8Error, FromUtf16Error}; /// Base functionality for all errors in Rust. pub trait Error: Send { @@ -117,3 +118,12 @@ impl Error for Utf8Error { fn detail(&self) -> Option<String> { Some(self.to_string()) } } + +impl Error for FromUtf8Error { + fn description(&self) -> &str { "invalid utf-8" } + fn detail(&self) -> Option<String> { Some(self.to_string()) } +} + +impl Error for FromUtf16Error { + fn description(&self) -> &str { "invalid utf-16" } +} diff --git a/src/libstd/fmt.rs b/src/libstd/fmt.rs index b75cf9a196b..957dd54a037 100644 --- a/src/libstd/fmt.rs +++ b/src/libstd/fmt.rs @@ -406,8 +406,6 @@ pub use core::fmt::{Argument, Arguments, write, radix, Radix, RadixFmt}; #[doc(hidden)] pub use core::fmt::{argument, argumentuint}; -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The format function takes a precompiled format string and a list of /// arguments, to return the resulting formatted string. /// @@ -431,31 +429,6 @@ pub fn format(args: Arguments) -> string::String { string::String::from_utf8(output).unwrap() } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// The format function takes a precompiled format string and a list of -/// arguments, to return the resulting formatted string. -/// -/// # Arguments -/// -/// * args - a structure of arguments generated via the `format_args!` macro. -/// -/// # Example -/// -/// ```rust -/// use std::fmt; -/// -/// let s = format_args!(fmt::format, "Hello, {}!", "world"); -/// assert_eq!(s, "Hello, world!".to_string()); -/// ``` -#[experimental = "this is an implementation detail of format! and should not \ - be called directly"] -pub fn format(args: &Arguments) -> string::String { - let mut output = Vec::new(); - let _ = write!(&mut output as &mut Writer, "{}", args); - string::String::from_utf8(output).unwrap() -} - impl<'a> Writer for Formatter<'a> { fn write(&mut self, b: &[u8]) -> io::IoResult<()> { match (*self).write(b) { diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs index 52e3c718b2d..737fef23c74 100644 --- a/src/libstd/hash.rs +++ b/src/libstd/hash.rs @@ -79,7 +79,7 @@ impl RandomSipHasher { /// Construct a new `RandomSipHasher` that is initialized with random keys. #[inline] pub fn new() -> RandomSipHasher { - let mut r = rand::task_rng(); + let mut r = rand::thread_rng(); let r0 = r.gen(); let r1 = r.gen(); RandomSipHasher { diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 1679d2e552f..ffd4122492b 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -39,7 +39,7 @@ use kinds::{Send,Sync}; /// let file = File::open(&Path::new("message.txt")); /// let mut reader = BufferedReader::new(file); /// -/// let mut buf = [0, ..100]; +/// let mut buf = [0; 100]; /// match reader.read(&mut buf) { /// Ok(nread) => println!("Read {} bytes", nread), /// Err(e) => println!("error reading: {}", e) @@ -104,7 +104,7 @@ impl<R: Reader> BufferedReader<R> { impl<R: Reader> Buffer for BufferedReader<R> { fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { if self.pos == self.cap { - self.cap = try!(self.inner.read(self.buf[mut])); + self.cap = try!(self.inner.read(self.buf.as_mut_slice())); self.pos = 0; } Ok(self.buf[self.pos..self.cap]) @@ -219,7 +219,7 @@ impl<W: Writer> Writer for BufferedWriter<W> { if buf.len() > self.buf.len() { self.inner.as_mut().unwrap().write(buf) } else { - let dst = self.buf[mut self.pos..]; + let dst = self.buf.slice_from_mut(self.pos); slice::bytes::copy_memory(dst, buf); self.pos += buf.len(); Ok(()) @@ -326,7 +326,7 @@ impl<W: Reader> Reader for InternalBufferedWriter<W> { /// stream.write("hello, world".as_bytes()); /// stream.flush(); /// -/// let mut buf = [0, ..100]; +/// let mut buf = [0; 100]; /// match stream.read(&mut buf) { /// Ok(nread) => println!("Read {} bytes", nread), /// Err(e) => println!("error reading: {}", e) @@ -439,9 +439,10 @@ mod test { impl Reader for ShortReader { fn read(&mut self, _: &mut [u8]) -> io::IoResult<uint> { - match self.lengths.remove(0) { - Some(i) => Ok(i), - None => Err(io::standard_error(io::EndOfFile)) + if self.lengths.is_empty() { + Err(io::standard_error(io::EndOfFile)) + } else { + Ok(self.lengths.remove(0)) } } } diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs index 7b8513ce423..3cdfa8beb07 100644 --- a/src/libstd/io/comm_adapters.rs +++ b/src/libstd/io/comm_adapters.rs @@ -30,7 +30,7 @@ use vec::Vec; /// # drop(tx); /// let mut reader = ChanReader::new(rx); /// -/// let mut buf = [0u8, ..100]; +/// let mut buf = [0u8; 100]; /// match reader.read(&mut buf) { /// Ok(nread) => println!("Read {} bytes", nread), /// Err(e) => println!("read error: {}", e), @@ -88,7 +88,7 @@ impl Reader for ChanReader { loop { let count = match self.fill_buf().ok() { Some(src) => { - let dst = buf[mut num_read..]; + let dst = buf.slice_from_mut(num_read); let count = cmp::min(src.len(), dst.len()); bytes::copy_memory(dst, src[..count]); count @@ -175,7 +175,7 @@ mod test { }).detach(); let mut reader = ChanReader::new(rx); - let mut buf = [0u8, ..3]; + let mut buf = [0u8; 3]; assert_eq!(Ok(0), reader.read(&mut [])); diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index dfea9678277..94dba1f7cc7 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -22,7 +22,7 @@ use num::Int; use ops::FnOnce; use option::Option; use option::Option::{Some, None}; -use ptr::RawPtr; +use ptr::PtrExt; use result::Result::{Ok, Err}; use slice::{SliceExt, AsSlice}; @@ -86,9 +86,9 @@ pub fn u64_to_le_bytes<T, F>(n: u64, size: uint, f: F) -> T where assert!(size <= 8u); match size { 1u => f(&[n as u8]), - 2u => f(unsafe { & transmute::<_, [u8, ..2]>((n as u16).to_le()) }), - 4u => f(unsafe { & transmute::<_, [u8, ..4]>((n as u32).to_le()) }), - 8u => f(unsafe { & transmute::<_, [u8, ..8]>(n.to_le()) }), + 2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_le()) }), + 4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_le()) }), + 8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_le()) }), _ => { let mut bytes = vec!(); @@ -127,9 +127,9 @@ pub fn u64_to_be_bytes<T, F>(n: u64, size: uint, f: F) -> T where assert!(size <= 8u); match size { 1u => f(&[n as u8]), - 2u => f(unsafe { & transmute::<_, [u8, ..2]>((n as u16).to_be()) }), - 4u => f(unsafe { & transmute::<_, [u8, ..4]>((n as u32).to_be()) }), - 8u => f(unsafe { & transmute::<_, [u8, ..8]>(n.to_be()) }), + 2u => f(unsafe { & transmute::<_, [u8; 2]>((n as u16).to_be()) }), + 4u => f(unsafe { & transmute::<_, [u8; 4]>((n as u32).to_be()) }), + 8u => f(unsafe { & transmute::<_, [u8; 8]>(n.to_be()) }), _ => { let mut bytes = vec!(); let mut i = size; @@ -164,7 +164,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 { panic!("index out of bounds"); } - let mut buf = [0u8, ..8]; + let mut buf = [0u8; 8]; unsafe { let ptr = data.as_ptr().offset(start as int); let out = buf.as_mut_ptr(); diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index 20920e60561..7fa5b3cfac7 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -558,6 +558,7 @@ pub fn walk_dir(path: &Path) -> IoResult<Directories> { } /// An iterator that walks over a directory +#[deriving(Clone)] pub struct Directories { stack: Vec<Path>, } @@ -881,7 +882,7 @@ mod test { } { let mut read_stream = File::open_mode(filename, Open, Read); - let mut read_buf = [0, .. 1028]; + let mut read_buf = [0; 1028]; let read_str = match check!(read_stream.read(&mut read_buf)) { -1|0 => panic!("shouldn't happen"), n => str::from_utf8(read_buf[..n]).unwrap().to_string() @@ -921,7 +922,7 @@ mod test { #[test] fn file_test_io_non_positional_read() { let message: &str = "ten-four"; - let mut read_mem = [0, .. 8]; + let mut read_mem = [0; 8]; let tmpdir = tmpdir(); let filename = &tmpdir.join("file_rt_io_file_test_positional.txt"); { @@ -931,11 +932,11 @@ mod test { { let mut read_stream = File::open_mode(filename, Open, Read); { - let read_buf = read_mem[mut 0..4]; + let read_buf = read_mem.slice_mut(0, 4); check!(read_stream.read(read_buf)); } { - let read_buf = read_mem[mut 4..8]; + let read_buf = read_mem.slice_mut(4, 8); check!(read_stream.read(read_buf)); } } @@ -947,7 +948,7 @@ mod test { #[test] fn file_test_io_seek_and_tell_smoke_test() { let message = "ten-four"; - let mut read_mem = [0, .. 4]; + let mut read_mem = [0; 4]; let set_cursor = 4 as u64; let mut tell_pos_pre_read; let mut tell_pos_post_read; @@ -977,7 +978,7 @@ mod test { let overwrite_msg = "-the-bar!!"; let final_msg = "foo-the-bar!!"; let seek_idx = 3i; - let mut read_mem = [0, .. 13]; + let mut read_mem = [0; 13]; let tmpdir = tmpdir(); let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt"); { @@ -1002,7 +1003,7 @@ mod test { let chunk_one: &str = "qwer"; let chunk_two: &str = "asdf"; let chunk_three: &str = "zxcv"; - let mut read_mem = [0, .. 4]; + let mut read_mem = [0; 4]; let tmpdir = tmpdir(); let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt"); { @@ -1104,7 +1105,7 @@ mod test { check!(w.write(msg)); } let files = check!(readdir(dir)); - let mut mem = [0u8, .. 4]; + let mut mem = [0u8; 4]; for f in files.iter() { { let n = f.filestem_str(); @@ -1136,7 +1137,7 @@ mod test { check!(File::create(&dir2.join("14"))); let mut files = check!(walk_dir(dir)); - let mut cur = [0u8, .. 2]; + let mut cur = [0u8; 2]; for f in files { let stem = f.filestem_str().unwrap(); let root = stem.as_bytes()[0] - b'0'; @@ -1149,6 +1150,19 @@ mod test { } #[test] + fn mkdir_path_already_exists_error() { + use io::{IoError, PathAlreadyExists}; + + let tmpdir = tmpdir(); + let dir = &tmpdir.join("mkdir_error_twice"); + check!(mkdir(dir, io::USER_RWX)); + match mkdir(dir, io::USER_RWX) { + Err(IoError{kind:PathAlreadyExists,..}) => (), + _ => assert!(false) + }; + } + + #[test] fn recursive_mkdir() { let tmpdir = tmpdir(); let dir = tmpdir.join("d1/d2"); @@ -1532,7 +1546,7 @@ mod test { fn binary_file() { use rand::{StdRng, Rng}; - let mut bytes = [0, ..1024]; + let mut bytes = [0; 1024]; StdRng::new().ok().unwrap().fill_bytes(&mut bytes); let tmpdir = tmpdir(); diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs index 71c42273c22..e5d95974edb 100644 --- a/src/libstd/io/mem.rs +++ b/src/libstd/io/mem.rs @@ -169,7 +169,7 @@ impl Reader for MemReader { let write_len = min(buf.len(), self.buf.len() - self.pos); { let input = self.buf[self.pos.. self.pos + write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -214,7 +214,7 @@ impl<'a> Reader for &'a [u8] { let write_len = min(buf.len(), self.len()); { let input = self[..write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); slice::bytes::copy_memory(output, input); } @@ -252,7 +252,7 @@ impl<'a> Buffer for &'a [u8] { /// # #![allow(unused_must_use)] /// use std::io::BufWriter; /// -/// let mut buf = [0, ..4]; +/// let mut buf = [0; 4]; /// { /// let mut w = BufWriter::new(&mut buf); /// w.write(&[0, 1, 2]); @@ -279,7 +279,7 @@ impl<'a> BufWriter<'a> { impl<'a> Writer for BufWriter<'a> { #[inline] fn write(&mut self, src: &[u8]) -> IoResult<()> { - let dst = self.buf[mut self.pos..]; + let dst = self.buf.slice_from_mut(self.pos); let dst_len = dst.len(); if dst_len == 0 { @@ -359,7 +359,7 @@ impl<'a> Reader for BufReader<'a> { let write_len = min(buf.len(), self.buf.len() - self.pos); { let input = self.buf[self.pos.. self.pos + write_len]; - let output = buf[mut ..write_len]; + let output = buf.slice_to_mut(write_len); assert_eq!(input.len(), output.len()); slice::bytes::copy_memory(output, input); } @@ -428,7 +428,7 @@ mod test { #[test] fn test_buf_writer() { - let mut buf = [0 as u8, ..9]; + let mut buf = [0 as u8; 9]; { let mut writer = BufWriter::new(&mut buf); assert_eq!(writer.tell(), Ok(0)); @@ -449,7 +449,7 @@ mod test { #[test] fn test_buf_writer_seek() { - let mut buf = [0 as u8, ..8]; + let mut buf = [0 as u8; 8]; { let mut writer = BufWriter::new(&mut buf); assert_eq!(writer.tell(), Ok(0)); @@ -478,7 +478,7 @@ mod test { #[test] fn test_buf_writer_error() { - let mut buf = [0 as u8, ..2]; + let mut buf = [0 as u8; 2]; let mut writer = BufWriter::new(&mut buf); writer.write(&[0]).unwrap(); @@ -499,7 +499,7 @@ mod test { assert_eq!(reader.tell(), Ok(1)); let b: &[_] = &[0]; assert_eq!(buf, b); - let mut buf = [0, ..4]; + let mut buf = [0; 4]; assert_eq!(reader.read(&mut buf), Ok(4)); assert_eq!(reader.tell(), Ok(5)); let b: &[_] = &[1, 2, 3, 4]; @@ -525,7 +525,7 @@ mod test { assert_eq!(reader.len(), 7); let b: &[_] = &[0]; assert_eq!(buf.as_slice(), b); - let mut buf = [0, ..4]; + let mut buf = [0; 4]; assert_eq!(reader.read(&mut buf), Ok(4)); assert_eq!(reader.len(), 3); let b: &[_] = &[1, 2, 3, 4]; @@ -552,7 +552,7 @@ mod test { assert_eq!(reader.tell(), Ok(1)); let b: &[_] = &[0]; assert_eq!(buf, b); - let mut buf = [0, ..4]; + let mut buf = [0; 4]; assert_eq!(reader.read(&mut buf), Ok(4)); assert_eq!(reader.tell(), Ok(5)); let b: &[_] = &[1, 2, 3, 4]; @@ -649,11 +649,11 @@ mod test { #[test] fn io_read_at_least() { let mut r = MemReader::new(vec![1, 2, 3, 4, 5, 6, 7, 8]); - let mut buf = [0, ..3]; + let mut buf = [0; 3]; assert!(r.read_at_least(buf.len(), &mut buf).is_ok()); let b: &[_] = &[1, 2, 3]; assert_eq!(buf, b); - assert!(r.read_at_least(0, buf[mut ..0]).is_ok()); + assert!(r.read_at_least(0, buf.slice_to_mut(0)).is_ok()); assert_eq!(buf, b); assert!(r.read_at_least(buf.len(), &mut buf).is_ok()); let b: &[_] = &[4, 5, 6]; @@ -722,13 +722,13 @@ mod test { #[bench] fn bench_mem_reader(b: &mut Bencher) { b.iter(|| { - let buf = [5 as u8, ..100].to_vec(); + let buf = [5 as u8; 100].to_vec(); { let mut rdr = MemReader::new(buf); for _i in range(0u, 10) { - let mut buf = [0 as u8, .. 10]; + let mut buf = [0 as u8; 10]; rdr.read(&mut buf).unwrap(); - assert_eq!(buf.as_slice(), [5, .. 10].as_slice()); + assert_eq!(buf.as_slice(), [5; 10].as_slice()); } } }); @@ -737,27 +737,27 @@ mod test { #[bench] fn bench_buf_writer(b: &mut Bencher) { b.iter(|| { - let mut buf = [0 as u8, ..100]; + let mut buf = [0 as u8; 100]; { let mut wr = BufWriter::new(&mut buf); for _i in range(0u, 10) { - wr.write(&[5, .. 10]).unwrap(); + wr.write(&[5; 10]).unwrap(); } } - assert_eq!(buf.as_slice(), [5, .. 100].as_slice()); + assert_eq!(buf.as_slice(), [5; 100].as_slice()); }); } #[bench] fn bench_buf_reader(b: &mut Bencher) { b.iter(|| { - let buf = [5 as u8, ..100]; + let buf = [5 as u8; 100]; { let mut rdr = BufReader::new(&buf); for _i in range(0u, 10) { - let mut buf = [0 as u8, .. 10]; + let mut buf = [0 as u8; 10]; rdr.read(&mut buf).unwrap(); - assert_eq!(buf, [5, .. 10]); + assert_eq!(buf, [5; 10]); } } }); diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 0f8b3de4804..93a9e04501e 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -513,7 +513,7 @@ pub trait Reader { while read < min { let mut zeroes = 0; loop { - match self.read(buf[mut read..]) { + match self.read(buf.slice_from_mut(read)) { Ok(0) => { zeroes += 1; if zeroes >= NO_PROGRESS_LIMIT { @@ -935,7 +935,7 @@ impl<'a> Reader for &'a mut (Reader+'a) { // API yet. If so, it should be a method on Vec. unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -> &'a mut [T] { use raw::Slice; - use ptr::RawPtr; + use ptr::PtrExt; assert!(start <= end); assert!(end <= v.capacity()); @@ -1017,8 +1017,6 @@ pub trait Writer { /// decide whether their stream needs to be buffered or not. fn flush(&mut self) -> IoResult<()> { Ok(()) } - // NOTE(stage0): Remove cfg after a snapshot - #[cfg(not(stage0))] /// Writes a formatted string into this writer, returning any error /// encountered. /// @@ -1057,45 +1055,6 @@ pub trait Writer { } - // NOTE(stage0): Remove method after a snapshot - #[cfg(stage0)] - /// Writes a formatted string into this writer, returning any error - /// encountered. - /// - /// This method is primarily used to interface with the `format_args!` - /// macro, but it is rare that this should explicitly be called. The - /// `write!` macro should be favored to invoke this method instead. - /// - /// # Errors - /// - /// This function will return any I/O error reported while formatting. - fn write_fmt(&mut self, fmt: &fmt::Arguments) -> IoResult<()> { - // Create a shim which translates a Writer to a FormatWriter and saves - // off I/O errors. instead of discarding them - struct Adaptor<'a, T:'a> { - inner: &'a mut T, - error: IoResult<()>, - } - - impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> { - fn write(&mut self, bytes: &[u8]) -> fmt::Result { - match self.inner.write(bytes) { - Ok(()) => Ok(()), - Err(e) => { - self.error = Err(e); - Err(fmt::Error) - } - } - } - } - - let mut output = Adaptor { inner: self, error: Ok(()) }; - match fmt::write(&mut output, fmt) { - Ok(()) => Ok(()), - Err(..) => output.error - } - } - /// Write a rust string into this sink. /// /// The bytes written will be the UTF-8 encoded version of the input string. @@ -1122,8 +1081,8 @@ pub trait Writer { /// Write a single char, encoded as UTF-8. #[inline] fn write_char(&mut self, c: char) -> IoResult<()> { - let mut buf = [0u8, ..4]; - let n = c.encode_utf8(buf[mut]).unwrap_or(0); + let mut buf = [0u8; 4]; + let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0); self.write(buf[..n]) } @@ -1555,7 +1514,7 @@ pub trait Buffer: Reader { { let mut start = 1; while start < width { - match try!(self.read(buf[mut start..width])) { + match try!(self.read(buf.slice_mut(start, width))) { n if n == width - start => break, n if n < width - start => { start += n; } _ => return Err(standard_error(InvalidInput)), @@ -1724,7 +1683,7 @@ pub fn standard_error(kind: IoErrorKind) -> IoError { /// A mode specifies how a file should be opened or created. These modes are /// passed to `File::open_mode` and are used to control where the file is /// positioned when it is initially opened. -#[deriving(Copy)] +#[deriving(Copy, Clone, PartialEq, Eq)] pub enum FileMode { /// Opens a file positioned at the beginning. Open, @@ -1736,7 +1695,7 @@ pub enum FileMode { /// Access permissions with which the file should be opened. `File`s /// opened with `Read` will return an error if written to. -#[deriving(Copy)] +#[deriving(Copy, Clone, PartialEq, Eq)] pub enum FileAccess { /// Read-only access, requests to write will result in an error Read, @@ -2009,7 +1968,7 @@ mod tests { fn test_read_at_least() { let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()), vec![GoodBehavior(uint::MAX)]); - let buf = &mut [0u8, ..5]; + let buf = &mut [0u8; 5]; assert!(r.read_at_least(1, buf).unwrap() >= 1); assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least assert!(r.read_at_least(0, buf).is_ok()); diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 18993aaa9d0..d86cb841f96 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -10,8 +10,8 @@ //! Synchronous DNS Resolution //! -//! Contains the functionality to perform DNS resolution in a style related to -//! `getaddrinfo()` +//! Contains the functionality to perform DNS resolution or reverse lookup, +//! in a style related to `getaddrinfo()` and `getnameinfo()`, respectively. #![allow(missing_docs)] @@ -24,6 +24,7 @@ use io::{IoResult}; use io::net::ip::{SocketAddr, IpAddr}; use option::Option; use option::Option::{Some, None}; +use string::String; use sys; use vec::Vec; @@ -83,6 +84,12 @@ pub fn get_host_addresses(host: &str) -> IoResult<Vec<IpAddr>> { lookup(Some(host), None, None).map(|a| a.into_iter().map(|i| i.address.ip).collect()) } +/// Reverse name resolution. Given an address, returns the corresponding +/// hostname. +pub fn get_address_name(addr: IpAddr) -> IoResult<String> { + sys::addrinfo::get_address_name(addr) +} + /// Full-fledged resolution. This function will perform a synchronous call to /// getaddrinfo, controlled by the parameters /// diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index ce6bac0f8c4..7ce1d1fc13b 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { } fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> { - let mut bs = [0u8, ..4]; + let mut bs = [0u8; 4]; let mut i = 0; while i < 4 { if i != 0 && self.read_given_char('.').is_none() { @@ -248,13 +248,13 @@ impl<'a> Parser<'a> { fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> { fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr { assert!(head.len() + tail.len() <= 8); - let mut gs = [0u16, ..8]; + let mut gs = [0u16; 8]; gs.clone_from_slice(head); - gs[mut 8 - tail.len() .. 8].clone_from_slice(tail); + gs.slice_mut(8 - tail.len(), 8).clone_from_slice(tail); Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7]) } - fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) { + fn read_groups(p: &mut Parser, groups: &mut [u16; 8], limit: uint) -> (uint, bool) { let mut i = 0; while i < limit { if i < limit - 1 { @@ -291,7 +291,7 @@ impl<'a> Parser<'a> { (i, false) } - let mut head = [0u16, ..8]; + let mut head = [0u16; 8]; let (head_size, head_ipv4) = read_groups(self, &mut head, 8); if head_size == 8 { @@ -310,7 +310,7 @@ impl<'a> Parser<'a> { return None; } - let mut tail = [0u16, ..8]; + let mut tail = [0u16; 8]; let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size); Some(ipv6_addr_from_head_tail(head[..head_size], tail[..tail_size])) } diff --git a/src/libstd/io/net/pipe.rs b/src/libstd/io/net/pipe.rs index 68f3a8e1836..daefdd28b30 100644 --- a/src/libstd/io/net/pipe.rs +++ b/src/libstd/io/net/pipe.rs @@ -676,7 +676,7 @@ mod tests { s.set_timeout(Some(20)); for i in range(0u, 1001) { - match s.write(&[0, .. 128 * 1024]) { + match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, Err(e) => panic!("{}", e), @@ -705,7 +705,7 @@ mod tests { rx.recv().unwrap(); let mut amt = 0; while amt < 100 * 128 * 1024 { - match s.read(&mut [0, ..128 * 1024]) { + match s.read(&mut [0;128 * 1024]) { Ok(n) => { amt += n; } Err(e) => panic!("{}", e), } @@ -720,7 +720,7 @@ mod tests { tx.send(()).unwrap(); for _ in range(0u, 100) { - assert!(s.write(&[0, ..128 * 1024]).is_ok()); + assert!(s.write(&[0;128 * 1024]).is_ok()); } } @@ -739,7 +739,7 @@ mod tests { let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); for i in range(0u, 1001) { - match s.write(&[0, .. 128 * 1024]) { + match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, Err(e) => panic!("{}", e), diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs index 57ffcfaad30..3e59aaa05ef 100644 --- a/src/libstd/io/net/tcp.rs +++ b/src/libstd/io/net/tcp.rs @@ -982,7 +982,7 @@ mod test { rx.recv().unwrap(); let mut c = TcpStream::connect(addr).unwrap(); - let mut b = [0, ..10]; + let mut b = [0; 10]; assert_eq!(c.read(&mut b), Ok(1)); c.write(&[1]).unwrap(); rx.recv().unwrap(); @@ -1259,7 +1259,7 @@ mod test { s.set_timeout(Some(20)); for i in range(0i, 1001) { - match s.write(&[0, .. 128 * 1024]) { + match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, Err(e) => panic!("{}", e), @@ -1283,7 +1283,7 @@ mod test { rx.recv().unwrap(); let mut amt = 0; while amt < 100 * 128 * 1024 { - match s.read(&mut [0, ..128 * 1024]) { + match s.read(&mut [0;128 * 1024]) { Ok(n) => { amt += n; } Err(e) => panic!("{}", e), } @@ -1298,7 +1298,7 @@ mod test { tx.send(()).unwrap(); for _ in range(0i, 100) { - assert!(s.write(&[0, ..128 * 1024]).is_ok()); + assert!(s.write(&[0;128 * 1024]).is_ok()); } } @@ -1317,7 +1317,7 @@ mod test { let mut s = a.accept().unwrap(); s.set_write_timeout(Some(20)); for i in range(0i, 1001) { - match s.write(&[0, .. 128 * 1024]) { + match s.write(&[0; 128 * 1024]) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, Err(e) => panic!("{}", e), diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index d6c379cc9f7..6c167359966 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -45,11 +45,11 @@ use sys_common; /// Err(e) => panic!("couldn't bind socket: {}", e), /// }; /// -/// let mut buf = [0, ..10]; +/// let mut buf = [0; 10]; /// match socket.recv_from(&mut buf) { /// Ok((amt, src)) => { /// // Send a reply to the socket we received data from -/// let buf = buf[mut ..amt]; +/// let buf = buf.slice_to_mut(amt); /// buf.reverse(); /// socket.send_to(buf, src); /// } @@ -347,7 +347,7 @@ mod test { let (tx2, rx2) = channel(); let _t = Thread::spawn(move|| { - let send_as = |ip, val: &[u8]| { + let send_as = |&:ip, val: &[u8]| { match UdpSocket::bind(ip) { Ok(client) => { let client = box client; @@ -602,7 +602,7 @@ mod test { a.set_write_timeout(Some(1000)); for _ in range(0u, 100) { - match a.send_to(&[0, ..4*1024], addr2) { + match a.send_to(&[0;4*1024], addr2) { Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {}, Err(IoError { kind: TimedOut, .. }) => break, Err(e) => panic!("other error: {}", e), diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs index ee376658283..09dcafb0218 100644 --- a/src/libstd/io/pipe.rs +++ b/src/libstd/io/pipe.rs @@ -132,7 +132,7 @@ mod test { rx.recv().unwrap(); // don't close the pipe until the other read has finished }); - let mut buf = [0, ..10]; + let mut buf = [0; 10]; input.read(&mut buf).unwrap(); tx.send(()).unwrap(); } diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs index 1e008287a31..fedc102e45d 100644 --- a/src/libstd/io/process.rs +++ b/src/libstd/io/process.rs @@ -1208,6 +1208,7 @@ mod tests { #[test] #[cfg(windows)] fn env_map_keys_ci() { + use c_str::ToCStr; use super::EnvKey; let mut cmd = Command::new(""); cmd.env("path", "foo"); diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 74b0930a145..156c37c3be7 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -146,7 +146,7 @@ impl StdinReader { /// ``` pub fn lock<'a>(&'a mut self) -> StdinReaderGuard<'a> { StdinReaderGuard { - inner: self.inner.lock() + inner: self.inner.lock().unwrap() } } @@ -155,7 +155,7 @@ impl StdinReader { /// The read is performed atomically - concurrent read calls in other /// threads will not interleave with this one. pub fn read_line(&mut self) -> IoResult<String> { - self.inner.lock().0.read_line() + self.inner.lock().unwrap().0.read_line() } /// Like `Buffer::read_until`. @@ -163,7 +163,7 @@ impl StdinReader { /// The read is performed atomically - concurrent read calls in other /// threads will not interleave with this one. pub fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> { - self.inner.lock().0.read_until(byte) + self.inner.lock().unwrap().0.read_until(byte) } /// Like `Buffer::read_char`. @@ -171,13 +171,13 @@ impl StdinReader { /// The read is performed atomically - concurrent read calls in other /// threads will not interleave with this one. pub fn read_char(&mut self) -> IoResult<char> { - self.inner.lock().0.read_char() + self.inner.lock().unwrap().0.read_char() } } impl Reader for StdinReader { fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { - self.inner.lock().0.read(buf) + self.inner.lock().unwrap().0.read(buf) } // We have to manually delegate all of these because the default impls call @@ -185,23 +185,23 @@ impl Reader for StdinReader { // incur the costs of repeated locking). fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> { - self.inner.lock().0.read_at_least(min, buf) + self.inner.lock().unwrap().0.read_at_least(min, buf) } fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> { - self.inner.lock().0.push_at_least(min, len, buf) + self.inner.lock().unwrap().0.push_at_least(min, len, buf) } fn read_to_end(&mut self) -> IoResult<Vec<u8>> { - self.inner.lock().0.read_to_end() + self.inner.lock().unwrap().0.read_to_end() } fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> { - self.inner.lock().0.read_le_uint_n(nbytes) + self.inner.lock().unwrap().0.read_le_uint_n(nbytes) } fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> { - self.inner.lock().0.read_be_uint_n(nbytes) + self.inner.lock().unwrap().0.read_be_uint_n(nbytes) } } @@ -334,7 +334,7 @@ pub fn set_stderr(stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> { // // io1 aliases io2 // }) // }) -fn with_task_stdout(f: |&mut Writer| -> IoResult<()>) { +fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> { let mut my_stdout = LOCAL_STDOUT.with(|slot| { slot.borrow_mut().take() }).unwrap_or_else(|| { @@ -378,38 +378,18 @@ pub fn println(s: &str) { }) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible /// with the `format_args!` macro. pub fn print_args(fmt: fmt::Arguments) { with_task_stdout(|io| write!(io, "{}", fmt)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible -/// with the `format_args!` macro. -pub fn print_args(fmt: &fmt::Arguments) { - with_task_stdout(|io| write!(io, "{}", fmt)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Similar to `println`, but takes a `fmt::Arguments` structure to be /// compatible with the `format_args!` macro. pub fn println_args(fmt: fmt::Arguments) { with_task_stdout(|io| writeln!(io, "{}", fmt)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// Similar to `println`, but takes a `fmt::Arguments` structure to be -/// compatible with the `format_args!` macro. -pub fn println_args(fmt: &fmt::Arguments) { - with_task_stdout(|io| writeln!(io, "{}", fmt)) -} - /// Representation of a reader of a standard input stream pub struct StdReader { inner: StdSource diff --git a/src/libstd/io/test.rs b/src/libstd/io/test.rs index 9c6033f37c9..7592e7692db 100644 --- a/src/libstd/io/test.rs +++ b/src/libstd/io/test.rs @@ -131,7 +131,7 @@ mod darwin_fd_limit { use os::last_os_error; // Fetch the kern.maxfilesperproc value - let mut mib: [libc::c_int, ..2] = [CTL_KERN, KERN_MAXFILESPERPROC]; + let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; let mut maxfiles: libc::c_int = 0; let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size, diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs index e073f76af82..de4270e705b 100644 --- a/src/libstd/io/timer.rs +++ b/src/libstd/io/timer.rs @@ -225,6 +225,8 @@ fn in_ms_u64(d: Duration) -> u64 { #[cfg(test)] mod test { + use prelude::v1::*; + use super::Timer; use thread::Thread; use time::Duration; diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index b22090e0f16..38ab71c172c 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -51,7 +51,7 @@ impl<R: Reader> Reader for LimitReader<R> { } let len = cmp::min(self.limit, buf.len()); - let res = self.inner.read(buf[mut ..len]); + let res = self.inner.read(buf.slice_to_mut(len)); match res { Ok(len) => self.limit -= len, _ => {} @@ -103,7 +103,7 @@ impl Reader for ZeroReader { impl Buffer for ZeroReader { fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> { - static DATA: [u8, ..64] = [0, ..64]; + static DATA: [u8; 64] = [0; 64]; Ok(DATA.as_slice()) } @@ -163,6 +163,7 @@ impl Writer for MultiWriter { /// A `Reader` which chains input from multiple `Reader`s, reading each to /// completion before moving onto the next. +#[deriving(Clone)] pub struct ChainedReader<I, R> { readers: I, cur_reader: Option<R>, @@ -234,7 +235,7 @@ impl<R: Reader, W: Writer> Reader for TeeReader<R, W> { /// Copies all data from a `Reader` to a `Writer`. pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> { - let mut buf = [0, ..super::DEFAULT_BUF_SIZE]; + let mut buf = [0; super::DEFAULT_BUF_SIZE]; loop { let len = match r.read(&mut buf) { Ok(len) => len, @@ -246,6 +247,7 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> { } /// An adaptor converting an `Iterator<u8>` to a `Reader`. +#[deriving(Clone)] pub struct IterReader<T> { iter: T, } @@ -276,11 +278,11 @@ impl<T: Iterator<u8>> Reader for IterReader<T> { #[cfg(test)] mod test { + use prelude::v1::*; + use io::{MemReader, ByRefReader}; use io; - use boxed::Box; use super::*; - use prelude::v1::*; #[test] fn test_limit_reader_unlimited() { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index aa1a0add068..6187593afd1 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -158,6 +158,7 @@ pub use alloc::rc; pub use core_collections::slice; pub use core_collections::str; pub use core_collections::string; +#[stable] pub use core_collections::vec; pub use unicode::char; diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 51a0853687e..47be8b2dcf9 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -17,8 +17,6 @@ #![experimental] #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The entry point for panic of Rust tasks. /// /// This macro is used to inject panic into a Rust task, causing the task to @@ -59,63 +57,6 @@ macro_rules! panic { }); } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// The entry point for panic of Rust tasks. -/// -/// This macro is used to inject panic into a Rust task, causing the task to -/// unwind and panic entirely. Each task's panic can be reaped as the -/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be -/// the value which is transmitted. -/// -/// The multi-argument form of this macro panics with a string and has the -/// `format!` syntax for building a string. -/// -/// # Example -/// -/// ```should_fail -/// # #![allow(unreachable_code)] -/// panic!(); -/// panic!("this is a terrible mistake!"); -/// panic!(4i); // panic with the value of 4 to be collected elsewhere -/// panic!("this is a {} {message}", "fancy", message = "message"); -/// ``` -#[macro_export] -macro_rules! panic { - () => ({ - panic!("explicit panic") - }); - ($msg:expr) => ({ - // static requires less code at runtime, more constant data - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind($msg, &_FILE_LINE) - }); - ($fmt:expr, $($arg:tt)*) => ({ - // a closure can't have return type !, so we need a full - // function to pass to format_args!, *and* we need the - // file and line numbers right here; so an inner bare fn - // is our only choice. - // - // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt - // is #[cold] and #[inline(never)] and because this is flagged as cold - // as returning !. We really do want this to be inlined, however, - // because it's just a tiny wrapper. Small wins (156K to 149K in size) - // were seen when forcing this to be inlined, and that number just goes - // up with the number of calls to panic!() - // - // The leading _'s are to avoid dead code warnings if this is - // used inside a dead function. Just `#[allow(dead_code)]` is - // insufficient, since the user may have - // `#[forbid(dead_code)]` and which cannot be overridden. - #[inline(always)] - fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! { - static _FILE_LINE: (&'static str, uint) = (file!(), line!()); - ::std::rt::begin_unwind_fmt(fmt, &_FILE_LINE) - } - format_args!(_run_fmt, $fmt, $($arg)*) - }); -} - /// Ensure that a boolean expression is `true` at runtime. /// /// This will invoke the `panic!` macro if the provided expression cannot be @@ -289,8 +230,6 @@ macro_rules! unimplemented { () => (panic!("not yet implemented")) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Use the syntax described in `std::fmt` to create a value of type `String`. /// See `std::fmt` for more information. /// @@ -307,28 +246,6 @@ macro_rules! format { ($($arg:tt)*) => (::std::fmt::format(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Use the syntax described in `std::fmt` to create a value of type `String`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// format!("test"); -/// format!("hello {}", "world!"); -/// format!("x = {}, y = {y}", 10i, y = 30i); -/// ``` -#[macro_export] -#[stable] -macro_rules! format { - ($($arg:tt)*) => ( - format_args!(::std::fmt::format, $($arg)*) - ) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. /// See `std::fmt` for more information. /// @@ -347,29 +264,6 @@ macro_rules! write { ($dst:expr, $($arg:tt)*) => ((&mut *$dst).write_fmt(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Use the `format!` syntax to write data into a buffer of type `&mut Writer`. -/// See `std::fmt` for more information. -/// -/// # Example -/// -/// ``` -/// # #![allow(unused_must_use)] -/// -/// let mut w = Vec::new(); -/// write!(&mut w, "test"); -/// write!(&mut w, "formatted {}", "arguments"); -/// ``` -#[macro_export] -#[stable] -macro_rules! write { - ($dst:expr, $($arg:tt)*) => ({ - let dst = &mut *$dst; - format_args!(|args| { dst.write_fmt(args) }, $($arg)*) - }) -} - /// Equivalent to the `write!` macro, except that a newline is appended after /// the message is written. #[macro_export] @@ -380,8 +274,6 @@ macro_rules! writeln { ) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Equivalent to the `println!` macro except that a newline is not printed at /// the end of the message. #[macro_export] @@ -390,18 +282,6 @@ macro_rules! print { ($($arg:tt)*) => (::std::io::stdio::print_args(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Equivalent to the `println!` macro except that a newline is not printed at -/// the end of the message. -#[macro_export] -#[stable] -macro_rules! print { - ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// Macro for printing to a task's stdout handle. /// /// Each task can override its stdout handle via `std::io::stdio::set_stdout`. @@ -420,26 +300,6 @@ macro_rules! println { ($($arg:tt)*) => (::std::io::stdio::println_args(format_args!($($arg)*))) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -/// Macro for printing to a task's stdout handle. -/// -/// Each task can override its stdout handle via `std::io::stdio::set_stdout`. -/// The syntax of this macro is the same as that used for `format!`. For more -/// information, see `std::fmt` and `std::io::stdio`. -/// -/// # Example -/// -/// ``` -/// println!("hello there!"); -/// println!("format {} arguments", "some"); -/// ``` -#[macro_export] -#[stable] -macro_rules! println { - ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*)) -} - /// Helper macro for unwrapping `Result` values while returning early with an /// error if the value of the expression is `Err`. For more information, see /// `std::io`. diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index b1f4e5acb93..febdf5f6118 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -104,7 +104,7 @@ fn int_to_str_bytes_common<T, F>(num: T, radix: uint, sign: SignFormat, mut f: F // This is just for integral types, the largest of which is a u64. The // smallest base that we can have is 2, so the most number of digits we're // ever going to have is 64 - let mut buf = [0u8, ..64]; + let mut buf = [0u8; 64]; let mut cur = 0; // Loop at least once to make sure at least a `0` gets emitted. @@ -321,10 +321,10 @@ pub fn float_to_str_bytes_common<T: Float>( // cut off the one extra digit, and depending on its value // round the remaining ones. if limit_digits && dig == digit_count { - let ascii2value = |chr: u8| { + let ascii2value = |&: chr: u8| { (chr as char).to_digit(radix).unwrap() }; - let value2ascii = |val: uint| { + let value2ascii = |&: val: uint| { char::from_digit(val, radix).unwrap() as u8 }; diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 61fd754018e..b52e4fda7af 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -38,7 +38,7 @@ pub fn to_str_bytes<U, F>(n: $T, radix: uint, f: F) -> U where use io::{Writer, Seek}; // The radix can be as low as 2, so we need at least 64 characters for a // base 2 number, and then we need another for a possible '-' character. - let mut buf = [0u8, ..65]; + let mut buf = [0u8; 65]; let amt = { let mut wr = ::io::BufWriter::new(&mut buf); (write!(&mut wr, "{}", ::fmt::radix(n, radix as u8))).unwrap(); diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 754b13886af..d115a15cc0b 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -46,7 +46,8 @@ use option::Option; use option::Option::{Some, None}; use path::{Path, GenericPath, BytesContainer}; use sys; -use ptr::RawPtr; +use sys::os as os_imp; +use ptr::PtrExt; use ptr; use result::Result; use result::Result::{Err, Ok}; @@ -619,10 +620,11 @@ pub fn get_exit_status() -> int { unsafe fn load_argc_and_argv(argc: int, argv: *const *const c_char) -> Vec<Vec<u8>> { use c_str::CString; + use iter::range; - Vec::from_fn(argc as uint, |i| { + range(0, argc as uint).map(|i| { CString::new(*argv.offset(i as int), false).as_bytes_no_nul().to_vec() - }) + }).collect() } /// Returns the command line arguments @@ -714,13 +716,14 @@ fn real_args() -> Vec<String> { #[cfg(windows)] fn real_args() -> Vec<String> { use slice; + use iter::range; let mut nArgs: c_int = 0; let lpArgCount: *mut c_int = &mut nArgs; let lpCmdLine = unsafe { GetCommandLineW() }; let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) }; - let args = Vec::from_fn(nArgs as uint, |i| unsafe { + let args: Vec<_> = range(0, nArgs as uint).map(|i| unsafe { // Determine the length of this argument. let ptr = *szArgList.offset(i as int); let mut len = 0; @@ -730,8 +733,8 @@ fn real_args() -> Vec<String> { let ptr = ptr as *const u16; let buf = slice::from_raw_buf(&ptr, len); let opt_s = String::from_utf16(sys::os::truncate_utf16_at_nul(buf)); - opt_s.expect("CommandLineToArgvW returned invalid UTF-16") - }); + opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16") + }).collect(); unsafe { LocalFree(szArgList as *mut c_void); @@ -1439,7 +1442,7 @@ mod tests { } fn make_rand_name() -> String { - let mut rng = rand::task_rng(); + let mut rng = rand::thread_rng(); let n = format!("TEST{}", rng.gen_ascii_chars().take(10u) .collect::<String>()); assert!(getenv(n.as_slice()).is_none()); diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 5c415239c5e..102da31a293 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -22,14 +22,14 @@ use option::Option::{None, Some}; use kinds::Sized; use str::{FromStr, Str}; use str; -use slice::{CloneSliceExt, Splits, AsSlice, VectorVector, +use slice::{CloneSliceExt, Split, AsSlice, SliceConcatExt, PartialEqSliceExt, SliceExt}; use vec::Vec; use super::{BytesContainer, GenericPath, GenericPathUnsafe}; /// Iterator that yields successive components of a Path as &[u8] -pub type Components<'a> = Splits<'a, u8, fn(&u8) -> bool>; +pub type Components<'a> = Split<'a, u8, fn(&u8) -> bool>; /// Iterator that yields successive components of a Path as Option<&str> pub type StrComponents<'a> = @@ -306,7 +306,7 @@ impl GenericPath for Path { } } } - Some(Path::new(comps.connect_vec(&SEP_BYTE))) + Some(Path::new(comps.as_slice().connect(&SEP_BYTE))) } } @@ -447,8 +447,16 @@ static dot_dot_static: &'static [u8] = b".."; #[cfg(test)] mod tests { - use prelude::v1::*; - use str; + use super::*; + + use clone::Clone; + use iter::{IteratorExt, DoubleEndedIteratorExt}; + use option::Option::{mod, Some, None}; + use path::GenericPath; + use slice::{AsSlice, SliceExt, CloneSliceExt}; + use str::{mod, Str, StrExt}; + use string::ToString; + use vec::Vec; macro_rules! t { (s: $path:expr, $exp:expr) => ( @@ -1236,7 +1244,7 @@ mod bench { extern crate test; use self::test::Bencher; use super::*; - use prelude::v1::*; + use prelude::v1::{Clone, GenericPath}; #[bench] fn join_home_dir(b: &mut Bencher) { diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 9117827ffc2..e047afc8eee 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -21,12 +21,12 @@ use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use hash; use io::Writer; use iter::{AdditiveIterator, DoubleEndedIteratorExt, Extend}; -use iter::{Iterator, IteratorExt, Map}; +use iter::{Iterator, IteratorExt, Map, repeat}; use mem; use option::Option; use option::Option::{Some, None}; -use slice::SliceExt; -use str::{CharSplits, FromStr, StrVector, StrExt}; +use slice::{SliceExt, SliceConcatExt}; +use str::{SplitTerminator, FromStr, StrExt}; use string::{String, ToString}; use unicode::char::UnicodeChar; use vec::Vec; @@ -38,7 +38,7 @@ use super::{contains_nul, BytesContainer, GenericPath, GenericPathUnsafe}; /// Each component is yielded as Option<&str> for compatibility with PosixPath, but /// every component in WindowsPath is guaranteed to be Some. pub type StrComponents<'a> = - Map<&'a str, Option<&'a str>, CharSplits<'a, char>, fn(&'a str) -> Option<&'a str>>; + Map<&'a str, Option<&'a str>, SplitTerminator<'a, char>, fn(&'a str) -> Option<&'a str>>; /// Iterator that yields successive components of a Path as &[u8] pub type Components<'a> = @@ -777,7 +777,7 @@ impl Path { } } } else if is_abs && comps.is_empty() { - Some(String::from_char(1, SEP)) + Some(repeat(SEP).take(1).collect()) } else { let prefix_ = s[0..prefix_len(prefix)]; let n = prefix_.len() + @@ -1127,6 +1127,15 @@ mod tests { use super::parse_prefix; use super::*; + use clone::Clone; + use iter::{IteratorExt, DoubleEndedIteratorExt}; + use option::Option::{mod, Some, None}; + use path::GenericPath; + use slice::{AsSlice, SliceExt, CloneSliceExt}; + use str::Str; + use string::ToString; + use vec::Vec; + macro_rules! t { (s: $path:expr, $exp:expr) => ( { diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 8c4189c37e7..33146f5e622 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -31,14 +31,15 @@ #[stable] #[doc(no_inline)] pub use iter::ExactSizeIterator; #[stable] #[doc(no_inline)] pub use iter::{Iterator, IteratorExt, Extend}; #[stable] #[doc(no_inline)] pub use iter::{IteratorCloneExt, IteratorOrdExt}; +#[stable] #[doc(no_inline)] pub use iter::IteratorPairExt; #[stable] #[doc(no_inline)] pub use option::Option::{mod, Some, None}; -#[stable] #[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr}; +#[stable] #[doc(no_inline)] pub use ptr::{PtrExt, MutPtrExt}; #[stable] #[doc(no_inline)] pub use result::Result::{mod, Ok, Err}; #[stable] #[doc(no_inline)] pub use slice::AsSlice; #[stable] #[doc(no_inline)] pub use slice::{BoxedSliceExt, SliceExt}; #[stable] #[doc(no_inline)] pub use slice::{CloneSliceExt, OrdSliceExt}; -#[stable] #[doc(no_inline)] pub use slice::{VectorVector, PartialEqSliceExt}; -#[stable] #[doc(no_inline)] pub use str::{Str, StrVector, StrExt}; +#[stable] #[doc(no_inline)] pub use slice::{PartialEqSliceExt, SliceConcatExt}; +#[stable] #[doc(no_inline)] pub use str::{Str, StrExt}; #[stable] #[doc(no_inline)] pub use string::{String, ToString}; #[stable] #[doc(no_inline)] pub use vec::Vec; diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 4371fe7e59a..86b8bfc7370 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -18,10 +18,10 @@ //! See the `distributions` submodule for sampling random numbers from //! distributions like normal and exponential. //! -//! # Task-local RNG +//! # Thread-local RNG //! -//! There is built-in support for a RNG associated with each task stored -//! in task-local storage. This RNG can be accessed via `task_rng`, or +//! There is built-in support for a RNG associated with each thread stored +//! in thread-local storage. This RNG can be accessed via `thread_rng`, or //! used implicitly via `random`. This RNG is normally randomly seeded //! from an operating-system source of randomness, e.g. `/dev/urandom` on //! Unix systems, and will automatically reseed itself from this source @@ -61,7 +61,7 @@ //! use std::rand; //! use std::rand::Rng; //! -//! let mut rng = rand::task_rng(); +//! let mut rng = rand::thread_rng(); //! if rng.gen() { // random bool //! println!("int: {}, uint: {}", rng.gen::<int>(), rng.gen::<uint>()) //! } @@ -97,7 +97,7 @@ //! //! fn main() { //! let between = Range::new(-1f64, 1.); -//! let mut rng = rand::task_rng(); +//! let mut rng = rand::thread_rng(); //! //! let total = 1_000_000u; //! let mut in_circle = 0u; @@ -183,7 +183,7 @@ //! // The estimation will be more accurate with more simulations //! let num_simulations = 10000u; //! -//! let mut rng = rand::task_rng(); +//! let mut rng = rand::thread_rng(); //! let random_door = Range::new(0u, 3); //! //! let (mut switch_wins, mut switch_losses) = (0u, 0u); @@ -257,7 +257,7 @@ impl StdRng { /// randomness from the operating system and use this in an /// expensive seeding operation. If one is only generating a small /// number of random numbers, or doesn't need the utmost speed for - /// generating each number, `task_rng` and/or `random` may be more + /// generating each number, `thread_rng` and/or `random` may be more /// appropriate. /// /// Reading the randomness from the OS may fail, and any error is @@ -307,28 +307,28 @@ pub fn weak_rng() -> XorShiftRng { } } -/// Controls how the task-local RNG is reseeded. -struct TaskRngReseeder; +/// Controls how the thread-local RNG is reseeded. +struct ThreadRngReseeder; -impl reseeding::Reseeder<StdRng> for TaskRngReseeder { +impl reseeding::Reseeder<StdRng> for ThreadRngReseeder { fn reseed(&mut self, rng: &mut StdRng) { *rng = match StdRng::new() { Ok(r) => r, - Err(e) => panic!("could not reseed task_rng: {}", e) + Err(e) => panic!("could not reseed thread_rng: {}", e) } } } -static TASK_RNG_RESEED_THRESHOLD: uint = 32_768; -type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>; +static THREAD_RNG_RESEED_THRESHOLD: uint = 32_768; +type ThreadRngInner = reseeding::ReseedingRng<StdRng, ThreadRngReseeder>; -/// The task-local RNG. -pub struct TaskRng { - rng: Rc<RefCell<TaskRngInner>>, +/// The thread-local RNG. +pub struct ThreadRng { + rng: Rc<RefCell<ThreadRngInner>>, } -/// Retrieve the lazily-initialized task-local random number +/// Retrieve the lazily-initialized thread-local random number /// generator, seeded by the system. Intended to be used in method -/// chaining style, e.g. `task_rng().gen::<int>()`. +/// chaining style, e.g. `thread_rng().gen::<int>()`. /// /// The RNG provided will reseed itself from the operating system /// after generating a certain amount of randomness. @@ -337,23 +337,23 @@ pub struct TaskRng { /// if the operating system random number generator is rigged to give /// the same sequence always. If absolute consistency is required, /// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`. -pub fn task_rng() -> TaskRng { +pub fn thread_rng() -> ThreadRng { // used to make space in TLS for a random number generator - thread_local!(static TASK_RNG_KEY: Rc<RefCell<TaskRngInner>> = { + thread_local!(static THREAD_RNG_KEY: Rc<RefCell<ThreadRngInner>> = { let r = match StdRng::new() { Ok(r) => r, - Err(e) => panic!("could not initialize task_rng: {}", e) + Err(e) => panic!("could not initialize thread_rng: {}", e) }; let rng = reseeding::ReseedingRng::new(r, - TASK_RNG_RESEED_THRESHOLD, - TaskRngReseeder); + THREAD_RNG_RESEED_THRESHOLD, + ThreadRngReseeder); Rc::new(RefCell::new(rng)) }); - TaskRng { rng: TASK_RNG_KEY.with(|t| t.clone()) } + ThreadRng { rng: THREAD_RNG_KEY.with(|t| t.clone()) } } -impl Rng for TaskRng { +impl Rng for ThreadRng { fn next_u32(&mut self) -> u32 { self.rng.borrow_mut().next_u32() } @@ -368,7 +368,7 @@ impl Rng for TaskRng { } } -/// Generates a random value using the task-local random number generator. +/// Generates a random value using the thread-local random number generator. /// /// `random()` can generate various types of random things, and so may require /// type hinting to generate the specific type you want. @@ -390,7 +390,7 @@ impl Rng for TaskRng { /// ``` #[inline] pub fn random<T: Rand>() -> T { - task_rng().gen() + thread_rng().gen() } /// Randomly sample up to `amount` elements from an iterator. @@ -398,9 +398,9 @@ pub fn random<T: Rand>() -> T { /// # Example /// /// ```rust -/// use std::rand::{task_rng, sample}; +/// use std::rand::{thread_rng, sample}; /// -/// let mut rng = task_rng(); +/// let mut rng = thread_rng(); /// let sample = sample(&mut rng, range(1i, 100), 5); /// println!("{}", sample); /// ``` @@ -420,7 +420,7 @@ pub fn sample<T, I: Iterator<T>, R: Rng>(rng: &mut R, #[cfg(test)] mod test { use prelude::v1::*; - use super::{Rng, task_rng, random, SeedableRng, StdRng, sample}; + use super::{Rng, thread_rng, random, SeedableRng, StdRng, sample}; use iter::order; struct ConstRng { i: u64 } @@ -453,7 +453,7 @@ mod test { #[test] fn test_gen_range() { - let mut r = task_rng(); + let mut r = thread_rng(); for _ in range(0u, 1000) { let a = r.gen_range(-3i, 42); assert!(a >= -3 && a < 42); @@ -473,20 +473,20 @@ mod test { #[test] #[should_fail] fn test_gen_range_panic_int() { - let mut r = task_rng(); + let mut r = thread_rng(); r.gen_range(5i, -2); } #[test] #[should_fail] fn test_gen_range_panic_uint() { - let mut r = task_rng(); + let mut r = thread_rng(); r.gen_range(5u, 2u); } #[test] fn test_gen_f64() { - let mut r = task_rng(); + let mut r = thread_rng(); let a = r.gen::<f64>(); let b = r.gen::<f64>(); debug!("{}", (a, b)); @@ -494,14 +494,14 @@ mod test { #[test] fn test_gen_weighted_bool() { - let mut r = task_rng(); + let mut r = thread_rng(); assert_eq!(r.gen_weighted_bool(0u), true); assert_eq!(r.gen_weighted_bool(1u), true); } #[test] fn test_gen_ascii_str() { - let mut r = task_rng(); + let mut r = thread_rng(); assert_eq!(r.gen_ascii_chars().take(0).count(), 0u); assert_eq!(r.gen_ascii_chars().take(10).count(), 10u); assert_eq!(r.gen_ascii_chars().take(16).count(), 16u); @@ -509,7 +509,7 @@ mod test { #[test] fn test_gen_vec() { - let mut r = task_rng(); + let mut r = thread_rng(); assert_eq!(r.gen_iter::<u8>().take(0).count(), 0u); assert_eq!(r.gen_iter::<u8>().take(10).count(), 10u); assert_eq!(r.gen_iter::<f64>().take(16).count(), 16u); @@ -517,7 +517,7 @@ mod test { #[test] fn test_choose() { - let mut r = task_rng(); + let mut r = thread_rng(); assert_eq!(r.choose(&[1i, 1, 1]).map(|&x|x), Some(1)); let v: &[int] = &[]; @@ -526,7 +526,7 @@ mod test { #[test] fn test_shuffle() { - let mut r = task_rng(); + let mut r = thread_rng(); let empty: &mut [int] = &mut []; r.shuffle(empty); let mut one = [1i]; @@ -545,8 +545,8 @@ mod test { } #[test] - fn test_task_rng() { - let mut r = task_rng(); + fn test_thread_rng() { + let mut r = thread_rng(); r.gen::<int>(); let mut v = [1i, 1, 1]; r.shuffle(&mut v); @@ -574,7 +574,7 @@ mod test { let min_val = 1i; let max_val = 100i; - let mut r = task_rng(); + let mut r = thread_rng(); let vals = range(min_val, max_val).collect::<Vec<int>>(); let small_sample = sample(&mut r, vals.iter(), 5); let large_sample = sample(&mut r, vals.iter(), vals.len() + 5); @@ -589,7 +589,7 @@ mod test { #[test] fn test_std_rng_seeded() { - let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>(); + let s = thread_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>(); let mut ra: StdRng = SeedableRng::from_seed(s.as_slice()); let mut rb: StdRng = SeedableRng::from_seed(s.as_slice()); assert!(order::equals(ra.gen_ascii_chars().take(100), @@ -598,7 +598,7 @@ mod test { #[test] fn test_std_rng_reseed() { - let s = task_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>(); + let s = thread_rng().gen_iter::<uint>().take(256).collect::<Vec<uint>>(); let mut r: StdRng = SeedableRng::from_seed(s.as_slice()); let string1 = r.gen_ascii_chars().take(100).collect::<String>(); @@ -669,7 +669,7 @@ mod bench { #[bench] fn rand_shuffle_100(b: &mut Bencher) { let mut rng = weak_rng(); - let x : &mut[uint] = &mut [1,..100]; + let x : &mut[uint] = &mut [1; 100]; b.iter(|| { rng.shuffle(x); }) diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 0a7b9d07636..6b60bcac9ca 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -55,7 +55,7 @@ mod imp { let mut read = 0; let len = v.len(); while read < len { - let result = getrandom(v[mut read..]); + let result = getrandom(v.slice_from_mut(read)); if result == -1 { let err = errno() as libc::c_int; if err == libc::EINTR { @@ -70,15 +70,15 @@ mod imp { } fn getrandom_next_u32() -> u32 { - let mut buf: [u8, ..4] = [0u8, ..4]; + let mut buf: [u8; 4] = [0u8; 4]; getrandom_fill_bytes(&mut buf); - unsafe { mem::transmute::<[u8, ..4], u32>(buf) } + unsafe { mem::transmute::<[u8; 4], u32>(buf) } } fn getrandom_next_u64() -> u64 { - let mut buf: [u8, ..8] = [0u8, ..8]; + let mut buf: [u8; 8] = [0u8; 8]; getrandom_fill_bytes(&mut buf); - unsafe { mem::transmute::<[u8, ..8], u64>(buf) } + unsafe { mem::transmute::<[u8; 8], u64>(buf) } } #[cfg(all(target_os = "linux", @@ -90,7 +90,7 @@ mod imp { static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL; if !GETRANDOM_CHECKED.load(Relaxed) { - let mut buf: [u8, ..0] = []; + let mut buf: [u8; 0] = []; let result = getrandom(&mut buf); let available = if result == -1 { let err = errno() as libc::c_int; @@ -170,6 +170,7 @@ mod imp { extern crate libc; use io::{IoResult}; + use kinds::Sync; use mem; use os; use rand::Rng; @@ -196,6 +197,8 @@ mod imp { #[repr(C)] struct SecRandom; + unsafe impl Sync for *const SecRandom {} + #[allow(non_upper_case_globals)] static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom; @@ -214,12 +217,12 @@ mod imp { impl Rng for OsRng { fn next_u32(&mut self) -> u32 { - let mut v = [0u8, .. 4]; + let mut v = [0u8; 4]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } fn next_u64(&mut self) -> u64 { - let mut v = [0u8, .. 8]; + let mut v = [0u8; 8]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } @@ -301,12 +304,12 @@ mod imp { impl Rng for OsRng { fn next_u32(&mut self) -> u32 { - let mut v = [0u8, .. 4]; + let mut v = [0u8; 4]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } fn next_u64(&mut self) -> u64 { - let mut v = [0u8, .. 8]; + let mut v = [0u8; 8]; self.fill_bytes(&mut v); unsafe { mem::transmute(v) } } @@ -349,7 +352,7 @@ mod test { r.next_u32(); r.next_u64(); - let mut v = [0u8, .. 1000]; + let mut v = [0u8; 1000]; r.fill_bytes(&mut v); } @@ -369,7 +372,7 @@ mod test { // as possible (XXX: is this a good test?) let mut r = OsRng::new().unwrap(); Thread::yield_now(); - let mut v = [0u8, .. 1000]; + let mut v = [0u8; 1000]; for _ in range(0u, 100) { r.next_u32(); diff --git a/src/libstd/rand/reader.rs b/src/libstd/rand/reader.rs index 642ab3d1e86..48d7f2e7854 100644 --- a/src/libstd/rand/reader.rs +++ b/src/libstd/rand/reader.rs @@ -105,7 +105,7 @@ mod test { #[test] fn test_reader_rng_fill_bytes() { let v = [1u8, 2, 3, 4, 5, 6, 7, 8]; - let mut w = [0u8, .. 8]; + let mut w = [0u8; 8]; let mut rng = ReaderRng::new(MemReader::new(v.as_slice().to_vec())); rng.fill_bytes(&mut w); @@ -117,7 +117,7 @@ mod test { #[should_fail] fn test_reader_rng_insufficient_bytes() { let mut rng = ReaderRng::new(MemReader::new(vec!())); - let mut v = [0u8, .. 3]; + let mut v = [0u8; 3]; rng.fill_bytes(&mut v); } } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 1fedf9652a0..4734a39c835 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -95,14 +95,14 @@ mod imp { } unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> { - Vec::from_fn(argc as uint, |i| { + range(0, argc as uint).map(|i| { let arg = *argv.offset(i as int); let mut len = 0u; while *arg.offset(len as int) != 0 { len += 1u; } slice::from_raw_buf(&arg, len).to_vec() - }) + }).collect() } #[cfg(test)] diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index d4101bb2152..4abef6ee910 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -60,19 +60,19 @@ mod test { t!("_ZN4$UP$E", "Box"); t!("_ZN8$UP$testE", "Boxtest"); t!("_ZN8$UP$test4foobE", "Boxtest::foob"); - t!("_ZN8$x20test4foobE", " test::foob"); + t!("_ZN10$u{20}test4foobE", " test::foob"); } #[test] fn demangle_many_dollars() { - t!("_ZN12test$x20test4foobE", "test test::foob"); + t!("_ZN14test$u{20}test4foobE", "test test::foob"); t!("_ZN12test$UP$test4foobE", "testBoxtest::foob"); } #[test] fn demangle_windows() { t!("ZN4testE", "test"); - t!("ZN12test$x20test4foobE", "test test::foob"); + t!("ZN14test$u{20}test4foobE", "test test::foob"); t!("ZN12test$UP$test4foobE", "testBoxtest::foob"); } } diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs index 2feea7fa0a4..4dbe878277d 100644 --- a/src/libstd/rt/libunwind.rs +++ b/src/libstd/rt/libunwind.rs @@ -82,7 +82,7 @@ pub const unwinder_private_data_size: uint = 2; pub struct _Unwind_Exception { pub exception_class: _Unwind_Exception_Class, pub exception_cleanup: _Unwind_Exception_Cleanup_Fn, - pub private: [_Unwind_Word, ..unwinder_private_data_size], + pub private: [_Unwind_Word; unwinder_private_data_size], } pub enum _Unwind_Context {} diff --git a/src/libstd/rt/macros.rs b/src/libstd/rt/macros.rs index 095a27203f9..0f35500a04a 100644 --- a/src/libstd/rt/macros.rs +++ b/src/libstd/rt/macros.rs @@ -15,22 +15,12 @@ #![macro_escape] -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] macro_rules! rterrln { ($fmt:expr $($arg:tt)*) => ( { ::rt::util::dumb_print(format_args!(concat!($fmt, "\n") $($arg)*)) } ) } -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! rterrln { - ($fmt:expr $($arg:tt)*) => ( { - format_args!(::rt::util::dumb_print, concat!($fmt, "\n") $($arg)*) - } ) -} - // Some basic logging. Enabled by passing `--cfg rtdebug` to the libstd build. macro_rules! rtdebug { ($($arg:tt)*) => ( { @@ -50,14 +40,6 @@ macro_rules! rtassert { } ) } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] macro_rules! rtabort { ($($arg:tt)*) => (::rt::util::abort(format_args!($($arg)*))) } - -// NOTE(stage0): Remove macro after a snapshot -#[cfg(stage0)] -macro_rules! rtabort { - ($($arg:tt)*) => (format_args!(::rt::util::abort, $($arg)*)) -} diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index eb446edbbd8..68aaa1b3ae5 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -49,7 +49,7 @@ pub mod args; mod at_exit_imp; mod libunwind; -/// The default error code of the rust runtime if the main task panics instead +/// The default error code of the rust runtime if the main thread panics instead /// of exiting cleanly. pub const DEFAULT_ERROR_CODE: int = 101; @@ -138,9 +138,9 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int { /// /// The procedure passed to this function will be executed as part of the /// runtime cleanup phase. For normal rust programs, this means that it will run -/// after all other tasks have exited. +/// after all other threads have exited. /// -/// The procedure is *not* executed with a local `Task` available to it, so +/// The procedure is *not* executed with a local `Thread` available to it, so /// primitives like logging, I/O, channels, spawning, etc, are *not* available. /// This is meant for "bare bones" usage to clean up runtime details, this is /// not meant as a general-purpose "let's clean everything up" function. diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index a8d5216e202..48cdfc20a35 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -36,7 +36,7 @@ use sys_common::stack; use rt::unwind; use rt::unwind::Unwinder; -/// State associated with Rust tasks. +/// State associated with Rust threads /// /// This structure is currently undergoing major changes, and is /// likely to be move/be merged with a `Thread` structure. @@ -50,14 +50,14 @@ pub struct Task { awoken: bool, // used to prevent spurious wakeups // This field holds the known bounds of the stack in (lo, hi) form. Not all - // native tasks necessarily know their precise bounds, hence this is + // native threads necessarily know their precise bounds, hence this is // optional. stack_bounds: (uint, uint), stack_guard: uint } -// Once a task has entered the `Armed` state it must be destroyed via `drop`, +// Once a thread has entered the `Armed` state it must be destroyed via `drop`, // and no other method. This state is used to track this transition. #[deriving(PartialEq)] enum TaskState { @@ -67,31 +67,31 @@ enum TaskState { } pub struct TaskOpts { - /// Invoke this procedure with the result of the task when it finishes. + /// Invoke this procedure with the result of the thread when it finishes. pub on_exit: Option<Thunk<Result>>, - /// A name for the task-to-be, for identification in panic messages + /// A name for the thread-to-be, for identification in panic messages pub name: Option<SendStr>, - /// The size of the stack for the spawned task + /// The size of the stack for the spawned thread pub stack_size: Option<uint>, } -/// Indicates the manner in which a task exited. +/// Indicates the manner in which a thread exited. /// -/// A task that completes without panicking is considered to exit successfully. +/// A thread that completes without panicking is considered to exit successfully. /// /// If you wish for this result's delivery to block until all -/// children tasks complete, recommend using a result future. +/// children threads complete, recommend using a result future. pub type Result = ::core::result::Result<(), Box<Any + Send>>; -/// A handle to a blocked task. Usually this means having the Box<Task> -/// pointer by ownership, but if the task is killable, a killer can steal it +/// A handle to a blocked thread. Usually this means having the Box<Task> +/// pointer by ownership, but if the thread is killable, a killer can steal it /// at any time. pub enum BlockedTask { Owned(Box<Task>), Shared(Arc<AtomicUint>), } -/// Per-task state related to task death, killing, panic, etc. +/// Per-thread state related to thread death, killing, panic, etc. pub struct Death { pub on_exit: Option<Thunk<Result>>, } @@ -101,7 +101,7 @@ pub struct BlockedTasks { } impl Task { - /// Creates a new uninitialized task. + /// Creates a new uninitialized thread. pub fn new(stack_bounds: Option<(uint, uint)>, stack_guard: Option<uint>) -> Task { Task { unwinder: Unwinder::new(), @@ -153,17 +153,17 @@ impl Task { }) } - /// Consumes ownership of a task, runs some code, and returns the task back. + /// Consumes ownership of a thread, runs some code, and returns the thread back. /// /// This function can be used as an emulated "try/catch" to interoperate /// with the rust runtime at the outermost boundary. It is not possible to /// use this function in a nested fashion (a try/catch inside of another /// try/catch). Invoking this function is quite cheap. /// - /// If the closure `f` succeeds, then the returned task can be used again + /// If the closure `f` succeeds, then the returned thread can be used again /// for another invocation of `run`. If the closure `f` panics then `self` /// will be internally destroyed along with all of the other associated - /// resources of this task. The `on_exit` callback is invoked with the + /// resources of this thread. The `on_exit` callback is invoked with the /// cause of panic (not returned here). This can be discovered by querying /// `is_destroyed()`. /// @@ -172,30 +172,30 @@ impl Task { /// guaranteed to return if it panicks. Care should be taken to ensure that /// stack references made by `f` are handled appropriately. /// - /// It is invalid to call this function with a task that has been previously + /// It is invalid to call this function with a thread that has been previously /// destroyed via a failed call to `run`. - pub fn run(mut self: Box<Task>, f: ||) -> Box<Task> { - assert!(!self.is_destroyed(), "cannot re-use a destroyed task"); + pub fn run<F>(mut self: Box<Task>, f: F) -> Box<Task> where F: FnOnce() { + assert!(!self.is_destroyed(), "cannot re-use a destroyed thread"); // First, make sure that no one else is in TLS. This does not allow // recursive invocations of run(). If there's no one else, then // relinquish ownership of ourselves back into TLS. if Local::exists(None::<Task>) { - panic!("cannot run a task recursively inside another"); + panic!("cannot run a thread recursively inside another"); } self.state = Armed; Local::put(self); // There are two primary reasons that general try/catch is unsafe. The // first is that we do not support nested try/catch. The above check for - // an existing task in TLS is sufficient for this invariant to be + // an existing thread in TLS is sufficient for this invariant to be // upheld. The second is that unwinding while unwinding is not defined. - // We take care of that by having an 'unwinding' flag in the task + // We take care of that by having an 'unwinding' flag in the thread // itself. For these reasons, this unsafety should be ok. let result = unsafe { unwind::try(f) }; - // After running the closure given return the task back out if it ran - // successfully, or clean up the task if it panicked. + // After running the closure given return the thread back out if it ran + // successfully, or clean up the thread if it panicked. let task: Box<Task> = Local::take(); match result { Ok(()) => task, @@ -203,13 +203,13 @@ impl Task { } } - /// Destroy all associated resources of this task. + /// Destroy all associated resources of this thread. /// - /// This function will perform any necessary clean up to prepare the task + /// This function will perform any necessary clean up to prepare the thread /// for destruction. It is required that this is called before a `Task` /// falls out of scope. /// - /// The returned task cannot be used for running any more code, but it may + /// The returned thread cannot be used for running any more code, but it may /// be used to extract the runtime as necessary. pub fn destroy(self: Box<Task>) -> Box<Task> { if self.is_destroyed() { @@ -219,14 +219,14 @@ impl Task { } } - /// Cleans up a task, processing the result of the task as appropriate. + /// Cleans up a thread, processing the result of the thread as appropriate. /// - /// This function consumes ownership of the task, deallocating it once it's + /// This function consumes ownership of the thread, deallocating it once it's /// done being processed. It is assumed that TLD and the local heap have /// already been destroyed and/or annihilated. fn cleanup(mut self: Box<Task>, result: Result) -> Box<Task> { // After taking care of the data above, we need to transmit the result - // of this task. + // of this thread. let what_to_do = self.death.on_exit.take(); Local::put(self); @@ -235,15 +235,15 @@ impl Task { // if this panics, this will also likely abort the runtime. // // This closure is currently limited to a channel send via the - // standard library's task interface, but this needs + // standard library's thread interface, but this needs // reconsideration to whether it's a reasonable thing to let a - // task to do or not. + // thread to do or not. match what_to_do { Some(f) => { f.invoke(result) } None => { drop(result) } } - // Now that we're done, we remove the task from TLS and flag it for + // Now that we're done, we remove the thread from TLS and flag it for // destruction. let mut task: Box<Task> = Local::take(); task.state = Destroyed; @@ -253,7 +253,7 @@ impl Task { /// Queries whether this can be destroyed or not. pub fn is_destroyed(&self) -> bool { self.state == Destroyed } - /// Deschedules the current task, invoking `f` `amt` times. It is not + /// Deschedules the current thread, invoking `f` `amt` times. It is not /// recommended to use this function directly, but rather communication /// primitives in `std::comm` should be used. // @@ -262,31 +262,31 @@ impl Task { // shared state. Additionally, all of the violations are protected with a // mutex, so in theory there are no races. // - // The first thing we need to do is to get a pointer to the task's internal - // mutex. This address will not be changing (because the task is allocated - // on the heap). We must have this handle separately because the task will + // The first thing we need to do is to get a pointer to the thread's internal + // mutex. This address will not be changing (because the thread is allocated + // on the heap). We must have this handle separately because the thread will // have its ownership transferred to the given closure. We're guaranteed, // however, that this memory will remain valid because *this* is the current - // task's execution thread. + // thread's execution thread. // - // The next weird part is where ownership of the task actually goes. We + // The next weird part is where ownership of the thread actually goes. We // relinquish it to the `f` blocking function, but upon returning this - // function needs to replace the task back in TLS. There is no communication - // from the wakeup thread back to this thread about the task pointer, and - // there's really no need to. In order to get around this, we cast the task + // function needs to replace the thread back in TLS. There is no communication + // from the wakeup thread back to this thread about the thread pointer, and + // there's really no need to. In order to get around this, we cast the thread // to a `uint` which is then used at the end of this function to cast back // to a `Box<Task>` object. Naturally, this looks like it violates // ownership semantics in that there may be two `Box<Task>` objects. // // The fun part is that the wakeup half of this implementation knows to - // "forget" the task on the other end. This means that the awakening half of + // "forget" the thread on the other end. This means that the awakening half of // things silently relinquishes ownership back to this thread, but not in a - // way that the compiler can understand. The task's memory is always valid - // for both tasks because these operations are all done inside of a mutex. + // way that the compiler can understand. The thread's memory is always valid + // for both threads because these operations are all done inside of a mutex. // // You'll also find that if blocking fails (the `f` function hands the // BlockedTask back to us), we will `mem::forget` the handles. The - // reasoning for this is the same logic as above in that the task silently + // reasoning for this is the same logic as above in that the thread silently // transfers ownership via the `uint`, not through normal compiler // semantics. // @@ -319,11 +319,11 @@ impl Task { let guard = (*me).lock.lock(); (*me).awoken = false; - // Apply the given closure to all of the "selectable tasks", + // Apply the given closure to all of the "selectable threads", // bailing on the first one that produces an error. Note that // care must be taken such that when an error is occurred, we - // may not own the task, so we may still have to wait for the - // task to become available. In other words, if task.wake() + // may not own the thread, so we may still have to wait for the + // thread to become available. In other words, if thread.wake() // returns `None`, then someone else has ownership and we must // wait for their signal. match iter.map(f).filter_map(|a| a.err()).next() { @@ -342,15 +342,15 @@ impl Task { guard.wait(); } } - // put the task back in TLS, and everything is as it once was. + // put the thread back in TLS, and everything is as it once was. Local::put(mem::transmute(me)); } } - /// Wakes up a previously blocked task. This function can only be - /// called on tasks that were previously blocked in `deschedule`. + /// Wakes up a previously blocked thread. This function can only be + /// called on threads that were previously blocked in `deschedule`. // - // See the comments on `deschedule` for why the task is forgotten here, and + // See the comments on `deschedule` for why the thread is forgotten here, and // why it's valid to do so. pub fn reawaken(mut self: Box<Task>) { unsafe { @@ -362,21 +362,21 @@ impl Task { } } - /// Yields control of this task to another task. This function will + /// Yields control of this thread to another thread. This function will /// eventually return, but possibly not immediately. This is used as an - /// opportunity to allow other tasks a chance to run. + /// opportunity to allow other threads a chance to run. pub fn yield_now() { Thread::yield_now(); } - /// Returns the stack bounds for this task in (lo, hi) format. The stack - /// bounds may not be known for all tasks, so the return value may be + /// Returns the stack bounds for this thread in (lo, hi) format. The stack + /// bounds may not be known for all threads, so the return value may be /// `None`. pub fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds } - /// Returns the stack guard for this task, if known. + /// Returns the stack guard for this thread, if known. pub fn stack_guard(&self) -> Option<uint> { if self.stack_guard != 0 { Some(self.stack_guard) @@ -385,9 +385,9 @@ impl Task { } } - /// Consume this task, flagging it as a candidate for destruction. + /// Consume this thread, flagging it as a candidate for destruction. /// - /// This function is required to be invoked to destroy a task. A task + /// This function is required to be invoked to destroy a thread. A thread /// destroyed through a normal drop will abort. pub fn drop(mut self) { self.state = Destroyed; @@ -396,7 +396,7 @@ impl Task { impl Drop for Task { fn drop(&mut self) { - rtdebug!("called drop for a task: {}", self as *mut Task as uint); + rtdebug!("called drop for a thread: {}", self as *mut Task as uint); rtassert!(self.state != Armed); } } @@ -414,7 +414,7 @@ impl Iterator<BlockedTask> for BlockedTasks { } impl BlockedTask { - /// Returns Some if the task was successfully woken; None if already killed. + /// Returns Some if the thread was successfully woken; None if already killed. pub fn wake(self) -> Option<Box<Task>> { match self { Owned(task) => Some(task), @@ -427,7 +427,7 @@ impl BlockedTask { } } - /// Reawakens this task if ownership is acquired. If finer-grained control + /// Reawakens this thread if ownership is acquired. If finer-grained control /// is desired, use `wake` instead. pub fn reawaken(self) { self.wake().map(|t| t.reawaken()); @@ -438,12 +438,12 @@ impl BlockedTask { #[cfg(not(test))] pub fn trash(self) { } #[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); } - /// Create a blocked task, unless the task was already killed. + /// Create a blocked thread, unless the thread was already killed. pub fn block(task: Box<Task>) -> BlockedTask { Owned(task) } - /// Converts one blocked task handle to a list of many handles to the same. + /// Converts one blocked thread handle to a list of many handles to the same. pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> { let arc = match self { Owned(task) => { @@ -543,7 +543,7 @@ mod test { drop(Task::new(None, None)); } - // Task blocking tests + // Thread blocking tests #[test] fn block_and_wake() { diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 8c35eb58284..dcd967a774c 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -79,11 +79,11 @@ struct Exception { pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: uint); -// Variables used for invoking callbacks when a task starts to unwind. +// Variables used for invoking callbacks when a thread starts to unwind. // // For more information, see below. const MAX_CALLBACKS: uint = 16; -static CALLBACKS: [atomic::AtomicUint, ..MAX_CALLBACKS] = +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, @@ -106,14 +106,14 @@ thread_local! { static PANICKING: Cell<bool> = Cell::new(false) } /// /// * This is not safe to call in a nested fashion. The unwinding /// interface for Rust is designed to have at most one try/catch block per -/// task, not multiple. No runtime checking is currently performed to uphold +/// thread, not multiple. No runtime checking is currently performed to uphold /// this invariant, so this function is not safe. A nested try/catch block /// may result in corruption of the outer try/catch block's state, especially -/// if this is used within a task itself. +/// if this is used within a thread itself. /// -/// * It is not sound to trigger unwinding while already unwinding. Rust tasks +/// * It is not sound to trigger unwinding while already unwinding. Rust threads /// have runtime checks in place to ensure this invariant, but it is not -/// guaranteed that a rust task is in place when invoking this function. +/// guaranteed that a rust thread is in place when invoking this function. /// Unwinding twice can lead to resource leaks where some destructors are not /// run. pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> { @@ -168,7 +168,7 @@ fn rust_panic(cause: Box<Any + Send>) -> ! { uwe: uw::_Unwind_Exception { exception_class: rust_exception_class(), exception_cleanup: exception_cleanup, - private: [0, ..uw::unwinder_private_data_size], + private: [0; uw::unwinder_private_data_size], }, cause: Some(cause), }; @@ -203,7 +203,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class { // _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase. // // This is pretty close to Rust's exception handling approach, except that Rust -// does have a single "catch-all" handler at the bottom of each task's stack. +// does have a single "catch-all" handler at the bottom of each thread's stack. // So we have two versions of the personality routine: // - rust_eh_personality, used by all cleanup landing pads, which never catches, // so the behavior of __gcc_personality_v0 is perfectly adequate there, and @@ -477,8 +477,6 @@ pub mod eabi { } } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] #[cfg(not(test))] /// Entry point of panic from the libcore crate. #[lang = "panic_fmt"] @@ -487,18 +485,6 @@ pub extern fn rust_begin_unwind(msg: fmt::Arguments, begin_unwind_fmt(msg, &(file, line)) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -#[cfg(not(test))] -/// Entry point of panic from the libcore crate. -#[lang = "panic_fmt"] -pub extern fn rust_begin_unwind(msg: &fmt::Arguments, - file: &'static str, line: uint) -> ! { - begin_unwind_fmt(msg, &(file, line)) -} - -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] /// The entry point for unwinding with a formatted message. /// /// This is designed to reduce the amount of code required at the call @@ -530,39 +516,6 @@ pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, uint)) - begin_unwind_inner(msg, file_line) } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -/// The entry point for unwinding with a formatted message. -/// -/// This is designed to reduce the amount of code required at the call -/// site as much as possible (so that `panic!()` has as low an impact -/// on (e.g.) the inlining of other functions as possible), by moving -/// the actual formatting into this shared place. -#[inline(never)] #[cold] -pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! { - use fmt::FormatWriter; - - // We do two allocations here, unfortunately. But (a) they're - // required with the current scheme, and (b) we don't handle - // panic + OOM properly anyway (see comment in begin_unwind - // below). - - struct VecWriter<'a> { v: &'a mut Vec<u8> } - - impl<'a> fmt::FormatWriter for VecWriter<'a> { - fn write(&mut self, buf: &[u8]) -> fmt::Result { - self.v.push_all(buf); - Ok(()) - } - } - - let mut v = Vec::new(); - let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg); - - let msg = box String::from_utf8_lossy(v.as_slice()).into_owned(); - begin_unwind_inner(msg, file_line) -} - /// This is the entry point of unwinding for panic!() and assert!(). #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! { @@ -570,7 +523,7 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> // Currently this means that panic!() on OOM will invoke this code path, // but then again we're not really ready for panic on OOM anyway. If // we do start doing this, then we should propagate this allocation to - // be performed in the parent of this task instead of the task that's + // be performed in the parent of this thread instead of the thread that's // panicking. // see below for why we do the `Any` coercion here. @@ -593,7 +546,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> static INIT: Once = ONCE_INIT; INIT.doit(|| unsafe { register(failure::on_fail); }); - // First, invoke call the user-defined callbacks triggered on task panic. + // First, invoke call the user-defined callbacks triggered on thread panic. // // By the time that we see a callback has been registered (by reading // MAX_CALLBACKS), the actual callback itself may have not been stored yet, @@ -621,7 +574,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> // If a thread panics while it's already unwinding then we // have limited options. Currently our preference is to // just abort. In the future we may consider resuming - // unwinding or otherwise exiting the task cleanly. + // unwinding or otherwise exiting the thread cleanly. rterrln!("thread panicked while panicking. aborting."); unsafe { intrinsics::abort() } } @@ -629,10 +582,10 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> rust_panic(msg); } -/// Register a callback to be invoked when a task unwinds. +/// Register a callback to be invoked when a thread unwinds. /// /// This is an unsafe and experimental API which allows for an arbitrary -/// callback to be invoked when a task panics. This callback is invoked on both +/// callback to be invoked when a thread panics. This callback is invoked on both /// the initial unwinding and a double unwinding if one occurs. Additionally, /// the local `Task` will be in place for the duration of the callback, and /// the callback must ensure that it remains in place once the callback returns. diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index d6c0e4a5aea..2a8deccb5dc 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -111,25 +111,11 @@ impl fmt::FormatWriter for Stdio { } } -// NOTE(stage0): Remove cfg after a snapshot -#[cfg(not(stage0))] pub fn dumb_print(args: fmt::Arguments) { let _ = Stderr.write_fmt(args); } -// NOTE(stage0): Remove function after a snapshot -#[cfg(stage0)] -pub fn dumb_print(args: &fmt::Arguments) { - let mut w = Stderr; - let _ = write!(&mut w, "{}", args); -} - -// NOTE(stage0): Remove wrappers after a snapshot -#[cfg(not(stage0))] pub fn abort(args: fmt::Arguments) -> ! { abort_(&args) } -#[cfg(stage0)] pub fn abort(args: &fmt::Arguments) -> ! { abort_(args) } - -// NOTE(stage0): Change to `pub fn abort(args: fmt::Arguments) -> !` after a snapshot -fn abort_(args: &fmt::Arguments) -> ! { +pub fn abort(args: fmt::Arguments) -> ! { use fmt::FormatWriter; struct BufWriter<'a> { @@ -138,7 +124,7 @@ fn abort_(args: &fmt::Arguments) -> ! { } impl<'a> FormatWriter for BufWriter<'a> { fn write(&mut self, bytes: &[u8]) -> fmt::Result { - let left = self.buf[mut self.pos..]; + let left = self.buf.slice_from_mut(self.pos); let to_write = bytes[..cmp::min(bytes.len(), left.len())]; slice::bytes::copy_memory(left, to_write); self.pos += to_write.len(); @@ -147,7 +133,7 @@ fn abort_(args: &fmt::Arguments) -> ! { } // Convert the arguments into a stack-allocated string - let mut msg = [0u8, ..512]; + let mut msg = [0u8; 512]; let mut w = BufWriter { buf: &mut msg, pos: 0 }; let _ = write!(&mut w, "{}", args); let msg = str::from_utf8(w.buf[mut ..w.pos]).unwrap_or("aborted"); diff --git a/src/libstd/sync/atomic.rs b/src/libstd/sync/atomic.rs index 5d45836af80..a88932f21cb 100644 --- a/src/libstd/sync/atomic.rs +++ b/src/libstd/sync/atomic.rs @@ -101,9 +101,9 @@ use core::mem; use core::prelude::{Send, Drop, None, Option, Some}; pub use core::atomic::{AtomicBool, AtomicInt, AtomicUint, AtomicPtr}; -pub use core::atomic::{Ordering, Relaxed, Release, Acquire, AcqRel, SeqCst}; pub use core::atomic::{INIT_ATOMIC_BOOL, INIT_ATOMIC_INT, INIT_ATOMIC_UINT}; pub use core::atomic::fence; +pub use core::atomic::Ordering::{mod, Relaxed, Release, Acquire, AcqRel, SeqCst}; /// An atomic, nullable unique pointer /// diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index 55d50af3b83..50e4f848d82 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -69,7 +69,7 @@ impl Barrier { /// Barriers are re-usable after all threads have rendezvoused once, and can /// be used continuously. pub fn wait(&self) { - let mut lock = self.lock.lock(); + let mut lock = self.lock.lock().unwrap(); let local_gen = lock.generation_id; lock.count += 1; if lock.count < self.num_threads { @@ -77,7 +77,7 @@ impl Barrier { // http://en.wikipedia.org/wiki/Spurious_wakeup while local_gen == lock.generation_id && lock.count < self.num_threads { - self.cvar.wait(&lock); + lock = self.cvar.wait(lock).unwrap(); } } else { lock.count = 0; diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 28960c1574e..d71cdeb25fd 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -11,10 +11,11 @@ use prelude::v1::*; use sync::atomic::{mod, AtomicUint}; -use sync::{mutex, StaticMutexGuard}; +use sync::poison::{mod, LockResult}; use sys_common::condvar as sys; use sys_common::mutex as sys_mutex; use time::Duration; +use sync::{mutex, MutexGuard}; /// A Condition Variable /// @@ -44,18 +45,19 @@ use time::Duration; /// // Inside of our lock, spawn a new thread, and then wait for it to start /// Thread::spawn(move|| { /// let &(ref lock, ref cvar) = &*pair2; -/// let mut started = lock.lock(); +/// let mut started = lock.lock().unwrap(); /// *started = true; /// cvar.notify_one(); /// }).detach(); /// /// // wait for the thread to start up /// let &(ref lock, ref cvar) = &*pair; -/// let started = lock.lock(); +/// let mut started = lock.lock().unwrap(); /// while !*started { -/// cvar.wait(&started); +/// started = cvar.wait(started).unwrap(); /// } /// ``` +#[stable] pub struct Condvar { inner: Box<StaticCondvar> } unsafe impl Send for Condvar {} @@ -73,6 +75,7 @@ unsafe impl Sync for Condvar {} /// /// static CVAR: StaticCondvar = CONDVAR_INIT; /// ``` +#[unstable = "may be merged with Condvar in the future"] pub struct StaticCondvar { inner: sys::Condvar, mutex: AtomicUint, @@ -82,24 +85,16 @@ unsafe impl Send for StaticCondvar {} unsafe impl Sync for StaticCondvar {} /// Constant initializer for a statically allocated condition variable. +#[unstable = "may be merged with Condvar in the future"] pub const CONDVAR_INIT: StaticCondvar = StaticCondvar { inner: sys::CONDVAR_INIT, mutex: atomic::INIT_ATOMIC_UINT, }; -/// A trait for vaules which can be passed to the waiting methods of condition -/// variables. This is implemented by the mutex guards in this module. -/// -/// Note that this trait should likely not be implemented manually unless you -/// really know what you're doing. -pub trait AsMutexGuard { - #[allow(missing_docs)] - unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard; -} - impl Condvar { /// Creates a new condition variable which is ready to be waited on and /// notified. + #[stable] pub fn new() -> Condvar { Condvar { inner: box StaticCondvar { @@ -113,8 +108,8 @@ impl Condvar { /// notification. /// /// This function will atomically unlock the mutex specified (represented by - /// `guard`) and block the current thread. This means that any calls to - /// `notify_*()` which happen logically after the mutex is unlocked are + /// `mutex_guard`) and block the current thread. This means that any calls + /// to `notify_*()` which happen logically after the mutex is unlocked are /// candidates to wake this thread up. When this function call returns, the /// lock specified will have been re-acquired. /// @@ -123,16 +118,24 @@ impl Condvar { /// the predicate must always be checked each time this function returns to /// protect against spurious wakeups. /// + /// # Failure + /// + /// This function will return an error if the mutex being waited on is + /// poisoned when this thread re-acquires the lock. For more information, + /// see information about poisoning on the Mutex type. + /// /// # Panics /// /// This function will `panic!()` if it is used with more than one mutex /// over time. Each condition variable is dynamically bound to exactly one /// mutex to ensure defined behavior across platforms. If this functionality /// is not desired, then unsafe primitives in `sys` are provided. - pub fn wait<T: AsMutexGuard>(&self, mutex_guard: &T) { + #[stable] + pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) + -> LockResult<MutexGuard<'a, T>> { unsafe { let me: &'static Condvar = &*(self as *const _); - me.inner.wait(mutex_guard) + me.inner.wait(guard) } } @@ -156,11 +159,11 @@ impl Condvar { // provide. There are also additional concerns about the unix-specific // implementation which may need to be addressed. #[allow(dead_code)] - fn wait_timeout<T: AsMutexGuard>(&self, mutex_guard: &T, - dur: Duration) -> bool { + fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { unsafe { let me: &'static Condvar = &*(self as *const _); - me.inner.wait_timeout(mutex_guard, dur) + me.inner.wait_timeout(guard, dur) } } @@ -171,6 +174,7 @@ impl Condvar { /// `notify_one` are not buffered in any way. /// /// To wake up all threads, see `notify_one()`. + #[stable] pub fn notify_one(&self) { unsafe { self.inner.inner.notify_one() } } /// Wake up all blocked threads on this condvar. @@ -180,6 +184,7 @@ impl Condvar { /// way. /// /// To wake up only one thread, see `notify_one()`. + #[stable] pub fn notify_all(&self) { unsafe { self.inner.inner.notify_all() } } } @@ -194,13 +199,19 @@ impl StaticCondvar { /// notification. /// /// See `Condvar::wait`. - pub fn wait<T: AsMutexGuard>(&'static self, mutex_guard: &T) { - unsafe { - let lock = mutex_guard.as_mutex_guard(); - let sys = mutex::guard_lock(lock); - self.verify(sys); - self.inner.wait(sys); - (*mutex::guard_poison(lock)).check("mutex"); + #[unstable = "may be merged with Condvar in the future"] + pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>) + -> LockResult<MutexGuard<'a, T>> { + let poisoned = unsafe { + let lock = mutex::guard_lock(&guard); + self.verify(lock); + self.inner.wait(lock); + mutex::guard_poison(&guard).get() + }; + if poisoned { + Err(poison::new_poison_error(guard)) + } else { + Ok(guard) } } @@ -209,26 +220,31 @@ impl StaticCondvar { /// /// See `Condvar::wait_timeout`. #[allow(dead_code)] // may want to stabilize this later, see wait_timeout above - fn wait_timeout<T: AsMutexGuard>(&'static self, mutex_guard: &T, - dur: Duration) -> bool { - unsafe { - let lock = mutex_guard.as_mutex_guard(); - let sys = mutex::guard_lock(lock); - self.verify(sys); - let ret = self.inner.wait_timeout(sys, dur); - (*mutex::guard_poison(lock)).check("mutex"); - return ret; + fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration) + -> LockResult<(MutexGuard<'a, T>, bool)> { + let (poisoned, success) = unsafe { + let lock = mutex::guard_lock(&guard); + self.verify(lock); + let success = self.inner.wait_timeout(lock, dur); + (mutex::guard_poison(&guard).get(), success) + }; + if poisoned { + Err(poison::new_poison_error((guard, success))) + } else { + Ok((guard, success)) } } /// Wake up one blocked thread on this condvar. /// /// See `Condvar::notify_one`. + #[unstable = "may be merged with Condvar in the future"] pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } } /// Wake up all blocked threads on this condvar. /// /// See `Condvar::notify_all`. + #[unstable = "may be merged with Condvar in the future"] pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } } /// Deallocate all resources associated with this static condvar. @@ -237,6 +253,7 @@ impl StaticCondvar { /// active users of the condvar, and this also doesn't prevent any future /// users of the condvar. This method is required to be called to not leak /// memory on all platforms. + #[unstable = "may be merged with Condvar in the future"] pub unsafe fn destroy(&'static self) { self.inner.destroy() } @@ -290,12 +307,12 @@ mod tests { static C: StaticCondvar = CONDVAR_INIT; static M: StaticMutex = MUTEX_INIT; - let g = M.lock(); + let mut g = M.lock().unwrap(); let _t = Thread::spawn(move|| { - let _g = M.lock(); + let _g = M.lock().unwrap(); C.notify_one(); }); - C.wait(&g); + let g = C.wait(g).unwrap(); drop(g); unsafe { C.destroy(); M.destroy(); } } @@ -311,13 +328,13 @@ mod tests { let tx = tx.clone(); Thread::spawn(move|| { let &(ref lock, ref cond) = &*data; - let mut cnt = lock.lock(); + let mut cnt = lock.lock().unwrap(); *cnt += 1; if *cnt == N { tx.send(()).unwrap(); } while *cnt != 0 { - cond.wait(&cnt); + cnt = cond.wait(cnt).unwrap(); } tx.send(()).unwrap(); }).detach(); @@ -326,7 +343,7 @@ mod tests { let &(ref lock, ref cond) = &*data; rx.recv().unwrap(); - let mut cnt = lock.lock(); + let mut cnt = lock.lock().unwrap(); *cnt = 0; cond.notify_all(); drop(cnt); @@ -341,13 +358,15 @@ mod tests { static C: StaticCondvar = CONDVAR_INIT; static M: StaticMutex = MUTEX_INIT; - let g = M.lock(); - assert!(!C.wait_timeout(&g, Duration::nanoseconds(1000))); - let _t = Thread::spawn(move|| { - let _g = M.lock(); + let g = M.lock().unwrap(); + let (g, success) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap(); + assert!(!success); + let _t = Thread::spawn(move || { + let _g = M.lock().unwrap(); C.notify_one(); }); - assert!(C.wait_timeout(&g, Duration::days(1))); + let (g, success) = C.wait_timeout(g, Duration::days(1)).unwrap(); + assert!(success); drop(g); unsafe { C.destroy(); M.destroy(); } } @@ -359,15 +378,14 @@ mod tests { static M2: StaticMutex = MUTEX_INIT; static C: StaticCondvar = CONDVAR_INIT; - let g = M1.lock(); + let mut g = M1.lock().unwrap(); let _t = Thread::spawn(move|| { - let _g = M1.lock(); + let _g = M1.lock().unwrap(); C.notify_one(); }); - C.wait(&g); + g = C.wait(g).unwrap(); drop(g); - C.wait(&M2.lock()); - + C.wait(M2.lock().unwrap()).unwrap(); } } diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 2b7311e4e98..1f8e5d7ee37 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -19,14 +19,15 @@ pub use alloc::arc::{Arc, Weak}; -pub use self::mutex::{Mutex, MutexGuard, StaticMutex, StaticMutexGuard, MUTEX_INIT}; +pub use self::mutex::{Mutex, MutexGuard, StaticMutex}; +pub use self::mutex::MUTEX_INIT; pub use self::rwlock::{RWLock, StaticRWLock, RWLOCK_INIT}; pub use self::rwlock::{RWLockReadGuard, RWLockWriteGuard}; -pub use self::rwlock::{StaticRWLockReadGuard, StaticRWLockWriteGuard}; -pub use self::condvar::{Condvar, StaticCondvar, CONDVAR_INIT, AsMutexGuard}; +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::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; pub use self::future::Future; pub use self::task_pool::TaskPool; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index e2294906229..413675f26d5 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -182,7 +182,7 @@ // senders. Under the hood, however, there are actually three flavors of // channels in play. // -// * Oneshots - these channels are highly optimized for the one-send use case. +// * Flavor::Oneshots - these channels are highly optimized for the one-send use case. // They contain as few atomics as possible and involve one and // exactly one allocation. // * Streams - these channels are optimized for the non-shared use case. They diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index e1606cb4317..e15c38cf9a1 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -86,7 +86,7 @@ impl<T: Send> Packet<T> { // and that could cause problems on platforms where it is // represented by opaque data structure pub fn postinit_lock(&self) -> MutexGuard<()> { - self.select_lock.lock() + self.select_lock.lock().unwrap() } // This function is used at the creation of a shared packet to inherit a @@ -435,7 +435,7 @@ impl<T: Send> Packet<T> { // about looking at and dealing with to_wake. Once we have acquired the // lock, we are guaranteed that inherit_blocker is done. { - let _guard = self.select_lock.lock(); + let _guard = self.select_lock.lock().unwrap(); } // Like the stream implementation, we want to make sure that the count diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 28005831d4f..98f1c4c46f9 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -121,9 +121,9 @@ fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>, NoneBlocked => {} _ => unreachable!(), } - drop(guard); // unlock - wait_token.wait(); // block - lock.lock() // relock + drop(guard); // unlock + wait_token.wait(); // block + lock.lock().unwrap() // relock } /// Wakes up a thread, dropping the lock at the correct time @@ -148,7 +148,7 @@ impl<T: Send> Packet<T> { tail: 0 as *mut Node, }, buf: Buffer { - buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None), + buf: range(0, cap + if cap == 0 {1} else {0}).map(|_| None).collect(), start: 0, size: 0, }, @@ -161,7 +161,7 @@ impl<T: Send> Packet<T> { fn acquire_send_slot(&self) -> MutexGuard<State<T>> { let mut node = Node { token: None, next: 0 as *mut Node }; loop { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); // are we ready to go? if guard.disconnected || guard.buf.size() < guard.buf.cap() { return guard; @@ -202,7 +202,7 @@ impl<T: Send> Packet<T> { } pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); if guard.disconnected { Err(super::TrySendError::Disconnected(t)) } else if guard.buf.size() == guard.buf.cap() { @@ -239,7 +239,7 @@ impl<T: Send> Packet<T> { // When reading this, remember that there can only ever be one receiver at // time. pub fn recv(&self) -> Result<T, ()> { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); // Wait for the buffer to have something in it. No need for a while loop // because we're the only receiver. @@ -258,7 +258,7 @@ impl<T: Send> Packet<T> { } pub fn try_recv(&self) -> Result<T, Failure> { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); // Easy cases first if guard.disconnected { return Err(Disconnected) } @@ -315,7 +315,7 @@ impl<T: Send> Packet<T> { } // Not much to do other than wake up a receiver if one's there - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); if guard.disconnected { return } guard.disconnected = true; match mem::replace(&mut guard.blocker, NoneBlocked) { @@ -326,7 +326,7 @@ impl<T: Send> Packet<T> { } pub fn drop_port(&self) { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); if guard.disconnected { return } guard.disconnected = true; @@ -372,14 +372,14 @@ impl<T: Send> Packet<T> { // If Ok, the value is whether this port has data, if Err, then the upgraded // port needs to be checked instead of this one. pub fn can_recv(&self) -> bool { - let guard = self.lock.lock(); + let guard = self.lock.lock().unwrap(); guard.disconnected || guard.buf.size() > 0 } // Attempts to start selection on this port. This can either succeed or fail // because there is data waiting. pub fn start_selection(&self, token: SignalToken) -> StartResult { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); if guard.disconnected || guard.buf.size() > 0 { Abort } else { @@ -397,7 +397,7 @@ impl<T: Send> Packet<T> { // // The return value indicates whether there's data on this port. pub fn abort_selection(&self) -> bool { - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); match mem::replace(&mut guard.blocker, NoneBlocked) { NoneBlocked => true, BlockedSender(token) => { @@ -413,7 +413,7 @@ impl<T: Send> Packet<T> { impl<T: Send> Drop for Packet<T> { fn drop(&mut self) { assert_eq!(self.channels.load(atomic::SeqCst), 0); - let mut guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); assert!(guard.queue.dequeue().is_none()); assert!(guard.canceled.is_none()); } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 1562031499f..3f155b02065 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -13,7 +13,7 @@ use prelude::v1::*; use cell::UnsafeCell; use kinds::marker; use ops::{Deref, DerefMut}; -use sync::{poison, AsMutexGuard}; +use sync::poison::{mod, TryLockError, TryLockResult, LockResult}; use sys_common::mutex as sys; /// A mutual exclusion primitive useful for protecting shared data @@ -27,12 +27,23 @@ use sys_common::mutex as sys; /// /// # Poisoning /// -/// In order to prevent access to otherwise invalid data, each mutex will -/// propagate any panics which occur while the lock is held. Once a thread has -/// panicked while holding the lock, then all other threads will immediately -/// panic as well once they hold the lock. +/// The mutexes in this module implement a strategy called "poisoning" where a +/// mutex is considered poisoned whenever a thread panics while holding the +/// lock. Once a mutex is poisoned, all other tasks are unable to access the +/// data by default as it is likely tainted (some invariant is not being +/// upheld). /// -/// # Example +/// For a mutex, this means that the `lock` and `try_lock` methods return a +/// `Result` which indicates whether a mutex has been poisoned or not. Most +/// usage of a mutex will simply `unwrap()` these results, propagating panics +/// among threads to ensure that a possibly invalid invariant is not witnessed. +/// +/// A poisoned mutex, however, does not prevent all access to the underlying +/// data. The `PoisonError` type has an `into_guard` method which will return +/// the guard that would have otherwise been returned on a successful lock. This +/// allows access to the data, despite the lock being poisoned. +/// +/// # Examples /// /// ```rust /// use std::sync::{Arc, Mutex}; @@ -51,11 +62,14 @@ use sys_common::mutex as sys; /// let (tx, rx) = channel(); /// for _ in range(0u, 10) { /// let (data, tx) = (data.clone(), tx.clone()); -/// Thread::spawn(move|| { +/// Thread::spawn(move || { /// // The shared static can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread /// // which can access the shared state when the lock is held. -/// let mut data = data.lock(); +/// // +/// // We unwrap() the return value to assert that we are not expecting +/// // tasks to ever fail while holding the lock. +/// let mut data = data.lock().unwrap(); /// *data += 1; /// if *data == N { /// tx.send(()).unwrap(); @@ -66,6 +80,36 @@ use sys_common::mutex as sys; /// /// rx.recv().unwrap(); /// ``` +/// +/// To recover from a poisoned mutex: +/// +/// ```rust +/// use std::sync::{Arc, Mutex}; +/// use std::thread::Thread; +/// +/// let lock = Arc::new(Mutex::new(0u)); +/// let lock2 = lock.clone(); +/// +/// let _ = Thread::spawn(move || -> () { +/// // This thread will acquire the mutex first, unwrapping the result of +/// // `lock` because the lock has not been poisoned. +/// let _lock = lock2.lock().unwrap(); +/// +/// // This panic while holding the lock (`_guard` is in scope) will poison +/// // the mutex. +/// panic!(); +/// }).join(); +/// +/// // The lock is poisoned by this point, but the returned result can be +/// // pattern matched on to return the underlying guard on both branches. +/// let mut guard = match lock.lock() { +/// Ok(guard) => guard, +/// Err(poisoned) => poisoned.into_guard(), +/// }; +/// +/// *guard += 1; +/// ``` +#[stable] pub struct Mutex<T> { // Note that this static mutex is in a *box*, not inlined into the struct // itself. Once a native mutex has been used once, its address can never @@ -96,14 +140,15 @@ unsafe impl<T:Send> Sync for Mutex<T> { } /// static LOCK: StaticMutex = MUTEX_INIT; /// /// { -/// let _g = LOCK.lock(); +/// let _g = LOCK.lock().unwrap(); /// // do some productive work /// } /// // lock is unlocked here. /// ``` +#[unstable = "may be merged with Mutex in the future"] pub struct StaticMutex { lock: sys::Mutex, - poison: UnsafeCell<poison::Flag>, + poison: poison::Flag, } unsafe impl Sync for StaticMutex {} @@ -114,31 +159,27 @@ unsafe impl Sync for StaticMutex {} /// The data protected by the mutex can be access through this guard via its /// Deref and DerefMut implementations #[must_use] +#[stable] pub struct MutexGuard<'a, T: 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). - __lock: &'a Mutex<T>, - __guard: StaticMutexGuard, -} - -/// An RAII implementation of a "scoped lock" of a static mutex. When this -/// structure is dropped (falls out of scope), the lock will be unlocked. -#[must_use] -pub struct StaticMutexGuard { - lock: &'static sys::Mutex, - marker: marker::NoSend, - poison: poison::Guard<'static>, + __lock: &'a StaticMutex, + __data: &'a UnsafeCell<T>, + __poison: poison::Guard, + __marker: marker::NoSend, } /// Static initialization of a mutex. This constant can be used to initialize /// other mutex constants. +#[unstable = "may be merged with Mutex in the future"] pub const MUTEX_INIT: StaticMutex = StaticMutex { lock: sys::MUTEX_INIT, - poison: UnsafeCell { value: poison::Flag { failed: false } }, + poison: poison::FLAG_INIT, }; impl<T: Send> Mutex<T> { /// Creates a new mutex in an unlocked state ready for use. + #[stable] pub fn new(t: T) -> Mutex<T> { Mutex { inner: box MUTEX_INIT, @@ -153,15 +194,14 @@ impl<T: Send> Mutex<T> { /// held. An RAII guard is returned to allow scoped unlock of the lock. When /// the guard goes out of scope, the mutex will be unlocked. /// - /// # Panics + /// # Failure /// /// If another user of this mutex panicked while holding the mutex, then - /// this call will immediately panic once the mutex is acquired. - pub fn lock(&self) -> MutexGuard<T> { - unsafe { - let lock: &'static StaticMutex = &*(&*self.inner as *const _); - MutexGuard::new(self, lock.lock()) - } + /// this call will return an error once the mutex is acquired. + #[stable] + pub fn lock(&self) -> LockResult<MutexGuard<T>> { + unsafe { self.inner.lock.lock() } + MutexGuard::new(&*self.inner, &self.data) } /// Attempts to acquire this lock. @@ -172,17 +212,17 @@ impl<T: Send> Mutex<T> { /// /// This function does not block. /// - /// # Panics + /// # Failure /// /// If another user of this mutex panicked while holding the mutex, then - /// this call will immediately panic if the mutex would otherwise be + /// this call will return failure if the mutex would otherwise be /// acquired. - pub fn try_lock(&self) -> Option<MutexGuard<T>> { - unsafe { - let lock: &'static StaticMutex = &*(&*self.inner as *const _); - lock.try_lock().map(|guard| { - MutexGuard::new(self, guard) - }) + #[stable] + pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> { + if unsafe { self.inner.lock.try_lock() } { + Ok(try!(MutexGuard::new(&*self.inner, &self.data))) + } else { + Err(TryLockError::WouldBlock) } } } @@ -197,19 +237,27 @@ impl<T: Send> Drop for Mutex<T> { } } +struct Dummy(UnsafeCell<()>); +unsafe impl Sync for Dummy {} +static DUMMY: Dummy = Dummy(UnsafeCell { value: () }); + impl StaticMutex { /// Acquires this lock, see `Mutex::lock` - pub fn lock(&'static self) -> StaticMutexGuard { + #[inline] + #[unstable = "may be merged with Mutex in the future"] + pub fn lock(&'static self) -> LockResult<MutexGuard<()>> { unsafe { self.lock.lock() } - StaticMutexGuard::new(self) + MutexGuard::new(self, &DUMMY.0) } /// Attempts to grab this lock, see `Mutex::try_lock` - pub fn try_lock(&'static self) -> Option<StaticMutexGuard> { + #[inline] + #[unstable = "may be merged with Mutex in the future"] + pub fn try_lock(&'static self) -> TryLockResult<MutexGuard<()>> { if unsafe { self.lock.try_lock() } { - Some(StaticMutexGuard::new(self)) + Ok(try!(MutexGuard::new(self, &DUMMY.0))) } else { - None + Err(TryLockError::WouldBlock) } } @@ -223,61 +271,54 @@ impl StaticMutex { /// *all* platforms. It may be the case that some platforms do not leak /// memory if this method is not called, but this is not guaranteed to be /// true on all platforms. + #[unstable = "may be merged with Mutex in the future"] pub unsafe fn destroy(&'static self) { self.lock.destroy() } } impl<'mutex, T> MutexGuard<'mutex, T> { - fn new(lock: &Mutex<T>, guard: StaticMutexGuard) -> MutexGuard<T> { - MutexGuard { __lock: lock, __guard: guard } + 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, + __marker: marker::NoSend, + } + }) } } -impl<'mutex, T> AsMutexGuard for MutexGuard<'mutex, T> { - unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { &self.__guard } -} - impl<'mutex, T> Deref<T> for MutexGuard<'mutex, T> { - fn deref<'a>(&'a self) -> &'a T { unsafe { &*self.__lock.data.get() } } + fn deref<'a>(&'a self) -> &'a T { + unsafe { &*self.__data.get() } + } } impl<'mutex, T> DerefMut<T> for MutexGuard<'mutex, T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { - unsafe { &mut *self.__lock.data.get() } + unsafe { &mut *self.__data.get() } } } -impl StaticMutexGuard { - fn new(lock: &'static StaticMutex) -> StaticMutexGuard { +#[unsafe_destructor] +impl<'a, T> Drop for MutexGuard<'a, T> { + #[inline] + fn drop(&mut self) { unsafe { - let guard = StaticMutexGuard { - lock: &lock.lock, - marker: marker::NoSend, - poison: (*lock.poison.get()).borrow(), - }; - guard.poison.check("mutex"); - return guard; + self.__lock.poison.done(&self.__poison); + self.__lock.lock.unlock(); } } } -pub fn guard_lock(guard: &StaticMutexGuard) -> &sys::Mutex { guard.lock } -pub fn guard_poison(guard: &StaticMutexGuard) -> &poison::Guard { - &guard.poison +pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { + &guard.__lock.lock } -impl AsMutexGuard for StaticMutexGuard { - unsafe fn as_mutex_guard(&self) -> &StaticMutexGuard { self } -} - -#[unsafe_destructor] -impl Drop for StaticMutexGuard { - fn drop(&mut self) { - unsafe { - self.poison.done(); - self.lock.unlock(); - } - } +pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { + &guard.__lock.poison } #[cfg(test)] @@ -296,16 +337,16 @@ mod test { #[test] fn smoke() { let m = Mutex::new(()); - drop(m.lock()); - drop(m.lock()); + drop(m.lock().unwrap()); + drop(m.lock().unwrap()); } #[test] fn smoke_static() { static M: StaticMutex = MUTEX_INIT; unsafe { - drop(M.lock()); - drop(M.lock()); + drop(M.lock().unwrap()); + drop(M.lock().unwrap()); M.destroy(); } } @@ -320,7 +361,7 @@ mod test { fn inc() { for _ in range(0, J) { unsafe { - let _g = M.lock(); + let _g = M.lock().unwrap(); CNT += 1; } } @@ -347,7 +388,7 @@ mod test { #[test] fn try_lock() { let m = Mutex::new(()); - assert!(m.try_lock().is_some()); + *m.try_lock().unwrap() = (); } #[test] @@ -359,22 +400,21 @@ mod test { // wait until parent gets in rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; - let mut lock = lock.lock(); + let mut lock = lock.lock().unwrap(); *lock = true; cvar.notify_one(); }); let &(ref lock, ref cvar) = &*packet.0; - let lock = lock.lock(); + let mut lock = lock.lock().unwrap(); tx.send(()).unwrap(); assert!(!*lock); while !*lock { - cvar.wait(&lock); + lock = cvar.wait(lock).unwrap(); } } #[test] - #[should_fail] fn test_arc_condvar_poison() { let packet = Packet(Arc::new((Mutex::new(1i), Condvar::new()))); let packet2 = Packet(packet.0.clone()); @@ -383,31 +423,35 @@ mod test { let _t = Thread::spawn(move || -> () { rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; - let _g = lock.lock(); + let _g = lock.lock().unwrap(); cvar.notify_one(); // Parent should fail when it wakes up. panic!(); }); let &(ref lock, ref cvar) = &*packet.0; - let lock = lock.lock(); + let mut lock = lock.lock().unwrap(); tx.send(()).unwrap(); while *lock == 1 { - cvar.wait(&lock); + match cvar.wait(lock) { + Ok(l) => { + lock = l; + assert_eq!(*lock, 1); + } + Err(..) => break, + } } } #[test] - #[should_fail] fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { - let lock = arc2.lock(); + Thread::spawn(move|| { + let lock = arc2.lock().unwrap(); assert_eq!(*lock, 2); }).join(); - let lock = arc.lock(); - assert_eq!(*lock, 1); + assert!(arc.lock().is_err()); } #[test] @@ -418,8 +462,8 @@ mod test { let arc2 = Arc::new(Mutex::new(arc)); let (tx, rx) = channel(); let _t = Thread::spawn(move|| { - let lock = arc2.lock(); - let lock2 = lock.lock(); + let lock = arc2.lock().unwrap(); + let lock2 = lock.lock().unwrap(); assert_eq!(*lock2, 1); tx.send(()).unwrap(); }); @@ -436,13 +480,13 @@ mod test { } impl Drop for Unwinder { fn drop(&mut self) { - *self.i.lock() += 1; + *self.i.lock().unwrap() += 1; } } let _u = Unwinder { i: arc2 }; panic!(); }).join(); - let lock = arc.lock(); + let lock = arc.lock().unwrap(); assert_eq!(*lock, 2); } } diff --git a/src/libstd/sync/poison.rs b/src/libstd/sync/poison.rs index ad08e9873fa..6e4df118209 100644 --- a/src/libstd/sync/poison.rs +++ b/src/libstd/sync/poison.rs @@ -8,31 +8,127 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::v1::*; + +use cell::UnsafeCell; +use error::FromError; +use fmt; use thread::Thread; -pub struct Flag { pub failed: bool } +pub struct Flag { failed: UnsafeCell<bool> } +pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } }; impl Flag { - pub fn borrow(&mut self) -> Guard { - Guard { flag: &mut self.failed, panicking: Thread::panicking() } + #[inline] + pub fn borrow(&self) -> LockResult<Guard> { + let ret = Guard { panicking: Thread::panicking() }; + if unsafe { *self.failed.get() } { + Err(new_poison_error(ret)) + } else { + Ok(ret) + } + } + + #[inline] + pub fn done(&self, guard: &Guard) { + if !guard.panicking && Thread::panicking() { + unsafe { *self.failed.get() = true; } + } + } + + #[inline] + pub fn get(&self) -> bool { + unsafe { *self.failed.get() } } } -pub struct Guard<'a> { - flag: &'a mut bool, +#[allow(missing_copy_implementations)] +pub struct Guard { panicking: bool, } -impl<'a> Guard<'a> { - pub fn check(&self, name: &str) { - if *self.flag { - panic!("poisoned {} - another task failed inside", name); - } +/// A type of error which can be returned whenever a lock is acquired. +/// +/// Both Mutexes and RWLocks are poisoned whenever a task fails while the lock +/// is held. The precise semantics for when a lock is poisoned is documented on +/// each lock, but once a lock is poisoned then all future acquisitions will +/// return this error. +#[stable] +pub struct PoisonError<T> { + guard: T, +} + +/// An enumeration of possible errors which can occur while calling the +/// `try_lock` method. +#[stable] +pub enum TryLockError<T> { + /// The lock could not be acquired because another task failed while holding + /// the lock. + #[stable] + Poisoned(PoisonError<T>), + /// The lock could not be acquired at this time because the operation would + /// otherwise block. + #[stable] + WouldBlock, +} + +/// A type alias for the result of a lock method which can be poisoned. +/// +/// The `Ok` variant of this result indicates that the primitive was not +/// poisoned, and the `Guard` is contained within. The `Err` variant indicates +/// that the primitive was poisoned. Note that the `Err` variant *also* carries +/// the associated guard, and it can be acquired through the `into_inner` +/// method. +#[stable] +pub type LockResult<Guard> = Result<Guard, PoisonError<Guard>>; + +/// A type alias for the result of a nonblocking locking method. +/// +/// For more information, see `LockResult`. A `TryLockResult` doesn't +/// necessarily hold the associated guard in the `Err` type as the lock may not +/// have been acquired for other reasons. +#[stable] +pub type TryLockResult<Guard> = Result<Guard, TryLockError<Guard>>; + +impl<T> fmt::Show for PoisonError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + "poisoned lock: another task failed inside".fmt(f) + } +} + +impl<T> PoisonError<T> { + /// Consumes this error indicating that a lock is poisoned, returning the + /// underlying guard to allow access regardless. + #[stable] + pub fn into_guard(self) -> T { self.guard } +} + +impl<T> FromError<PoisonError<T>> for TryLockError<T> { + fn from_error(err: PoisonError<T>) -> TryLockError<T> { + TryLockError::Poisoned(err) } +} - pub fn done(&mut self) { - if !self.panicking && Thread::panicking() { - *self.flag = true; +impl<T> fmt::Show for TryLockError<T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + TryLockError::Poisoned(ref p) => p.fmt(f), + TryLockError::WouldBlock => { + "try_lock failed because the operation would block".fmt(f) + } } } } + +pub fn new_poison_error<T>(guard: T) -> PoisonError<T> { + PoisonError { guard: guard } +} + +pub fn map_result<T, U, F>(result: LockResult<T>, f: F) + -> LockResult<U> + where F: FnOnce(T) -> U { + match result { + Ok(t) => Ok(f(t)), + Err(PoisonError { guard }) => Err(new_poison_error(f(guard))) + } +} diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 3c4283c72e2..b23fff31c0a 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -13,7 +13,7 @@ use prelude::v1::*; use cell::UnsafeCell; use kinds::marker; use ops::{Deref, DerefMut}; -use sync::poison; +use sync::poison::{mod, LockResult, TryLockError, TryLockResult}; use sys_common::rwlock as sys; /// A reader-writer lock @@ -29,12 +29,14 @@ use sys_common::rwlock as sys; /// locking methods implement `Deref` (and `DerefMut` for the `write` methods) /// to allow access to the contained of the lock. /// +/// # Poisoning +/// /// RWLocks, like Mutexes, will become poisoned on panics. Note, however, that /// an RWLock may only be poisoned if a panic occurs while it is locked /// exclusively (write mode). If a panic occurs in any reader, then the lock /// will not be poisoned. /// -/// # Example +/// # Examples /// /// ``` /// use std::sync::RWLock; @@ -43,19 +45,20 @@ use sys_common::rwlock as sys; /// /// // many reader locks can be held at once /// { -/// let r1 = lock.read(); -/// let r2 = lock.read(); +/// let r1 = lock.read().unwrap(); +/// let r2 = lock.read().unwrap(); /// assert_eq!(*r1, 5); /// assert_eq!(*r2, 5); /// } // read locks are dropped at this point /// /// // only one write lock may be held, however /// { -/// let mut w = lock.write(); +/// let mut w = lock.write().unwrap(); /// *w += 1; /// assert_eq!(*w, 6); /// } // write lock is dropped here /// ``` +#[stable] pub struct RWLock<T> { inner: Box<StaticRWLock>, data: UnsafeCell<T>, @@ -78,64 +81,55 @@ unsafe impl<T> Sync for RWLock<T> {} /// static LOCK: StaticRWLock = RWLOCK_INIT; /// /// { -/// let _g = LOCK.read(); +/// let _g = LOCK.read().unwrap(); /// // ... shared read access /// } /// { -/// let _g = LOCK.write(); +/// let _g = LOCK.write().unwrap(); /// // ... exclusive write access /// } /// unsafe { LOCK.destroy() } // free all resources /// ``` +#[unstable = "may be merged with RWLock in the future"] pub struct StaticRWLock { - inner: sys::RWLock, - poison: UnsafeCell<poison::Flag>, + lock: sys::RWLock, + poison: poison::Flag, } unsafe impl Send for StaticRWLock {} unsafe impl Sync for StaticRWLock {} /// Constant initialization for a statically-initialized rwlock. +#[unstable = "may be merged with RWLock in the future"] pub const RWLOCK_INIT: StaticRWLock = StaticRWLock { - inner: sys::RWLOCK_INIT, - poison: UnsafeCell { value: poison::Flag { failed: false } }, + lock: sys::RWLOCK_INIT, + poison: poison::FLAG_INIT, }; /// RAII structure used to release the shared read access of a lock when /// dropped. #[must_use] +#[stable] pub struct RWLockReadGuard<'a, T: 'a> { - __lock: &'a RWLock<T>, - __guard: StaticRWLockReadGuard, + __lock: &'a StaticRWLock, + __data: &'a UnsafeCell<T>, + __marker: marker::NoSend, } /// RAII structure used to release the exclusive write access of a lock when /// dropped. #[must_use] +#[stable] pub struct RWLockWriteGuard<'a, T: 'a> { - __lock: &'a RWLock<T>, - __guard: StaticRWLockWriteGuard, -} - -/// RAII structure used to release the shared read access of a lock when -/// dropped. -#[must_use] -pub struct StaticRWLockReadGuard { - lock: &'static sys::RWLock, - marker: marker::NoSend, -} - -/// RAII structure used to release the exclusive write access of a lock when -/// dropped. -#[must_use] -pub struct StaticRWLockWriteGuard { - lock: &'static sys::RWLock, - marker: marker::NoSend, - poison: poison::Guard<'static>, + __lock: &'a StaticRWLock, + __data: &'a UnsafeCell<T>, + __poison: poison::Guard, + __marker: marker::NoSend, } impl<T: Send + Sync> RWLock<T> { /// Creates a new instance of an RWLock which is unlocked and read to go. + #[stable] pub fn new(t: T) -> RWLock<T> { RWLock { inner: box RWLOCK_INIT, data: UnsafeCell::new(t) } } @@ -152,17 +146,16 @@ impl<T: Send + Sync> RWLock<T> { /// Returns an RAII guard which will release this thread's shared access /// once it is dropped. /// - /// # Panics + /// # Failure /// - /// This function will panic if the RWLock is poisoned. An RWLock is - /// poisoned whenever a writer panics while holding an exclusive lock. The - /// panic will occur immediately after the lock has been acquired. + /// This function will return an error if the RWLock is poisoned. An RWLock + /// is poisoned whenever a writer panics while holding an exclusive lock. + /// The failure will occur immediately after the lock has been acquired. #[inline] - pub fn read(&self) -> RWLockReadGuard<T> { - unsafe { - let lock: &'static StaticRWLock = &*(&*self.inner as *const _); - RWLockReadGuard::new(self, lock.read()) - } + #[stable] + pub fn read(&self) -> LockResult<RWLockReadGuard<T>> { + unsafe { self.inner.lock.read() } + RWLockReadGuard::new(&*self.inner, &self.data) } /// Attempt to acquire this lock with shared read access. @@ -174,18 +167,19 @@ impl<T: Send + Sync> RWLock<T> { /// guarantees with respect to the ordering of whether contentious readers /// or writers will acquire the lock first. /// - /// # Panics + /// # Failure /// - /// This function will panic if the RWLock is poisoned. An RWLock is - /// poisoned whenever a writer panics while holding an exclusive lock. A - /// panic will only occur if the lock is acquired. + /// This function will return an error if the RWLock is poisoned. An RWLock + /// is poisoned whenever a writer panics while holding an exclusive lock. An + /// error will only be returned if the lock would have otherwise been + /// acquired. #[inline] - pub fn try_read(&self) -> Option<RWLockReadGuard<T>> { - unsafe { - let lock: &'static StaticRWLock = &*(&*self.inner as *const _); - lock.try_read().map(|guard| { - RWLockReadGuard::new(self, guard) - }) + #[stable] + pub fn try_read(&self) -> TryLockResult<RWLockReadGuard<T>> { + if unsafe { self.inner.lock.try_read() } { + Ok(try!(RWLockReadGuard::new(&*self.inner, &self.data))) + } else { + Err(TryLockError::WouldBlock) } } @@ -198,17 +192,16 @@ impl<T: Send + Sync> RWLock<T> { /// Returns an RAII guard which will drop the write access of this rwlock /// when dropped. /// - /// # Panics + /// # Failure /// - /// This function will panic if the RWLock is poisoned. An RWLock is - /// poisoned whenever a writer panics while holding an exclusive lock. The - /// panic will occur when the lock is acquired. + /// This function will return an error if the RWLock is poisoned. An RWLock + /// is poisoned whenever a writer panics while holding an exclusive lock. + /// An error will be returned when the lock is acquired. #[inline] - pub fn write(&self) -> RWLockWriteGuard<T> { - unsafe { - let lock: &'static StaticRWLock = &*(&*self.inner as *const _); - RWLockWriteGuard::new(self, lock.write()) - } + #[stable] + pub fn write(&self) -> LockResult<RWLockWriteGuard<T>> { + unsafe { self.inner.lock.write() } + RWLockWriteGuard::new(&*self.inner, &self.data) } /// Attempt to lock this rwlock with exclusive write access. @@ -217,18 +210,19 @@ impl<T: Send + Sync> RWLock<T> { /// to `write` would otherwise block. If successful, an RAII guard is /// returned. /// - /// # Panics + /// # Failure /// - /// This function will panic if the RWLock is poisoned. An RWLock is - /// poisoned whenever a writer panics while holding an exclusive lock. A - /// panic will only occur if the lock is acquired. + /// This function will return an error if the RWLock is poisoned. An RWLock + /// is poisoned whenever a writer panics while holding an exclusive lock. An + /// error will only be returned if the lock would have otherwise been + /// acquired. #[inline] - pub fn try_write(&self) -> Option<RWLockWriteGuard<T>> { - unsafe { - let lock: &'static StaticRWLock = &*(&*self.inner as *const _); - lock.try_write().map(|guard| { - RWLockWriteGuard::new(self, guard) - }) + #[stable] + pub fn try_write(&self) -> TryLockResult<RWLockWriteGuard<T>> { + if unsafe { self.inner.lock.try_read() } { + Ok(try!(RWLockWriteGuard::new(&*self.inner, &self.data))) + } else { + Err(TryLockError::WouldBlock) } } } @@ -236,30 +230,37 @@ impl<T: Send + Sync> RWLock<T> { #[unsafe_destructor] impl<T> Drop for RWLock<T> { fn drop(&mut self) { - unsafe { self.inner.inner.destroy() } + unsafe { self.inner.lock.destroy() } } } +struct Dummy(UnsafeCell<()>); +unsafe impl Sync for Dummy {} +static DUMMY: Dummy = Dummy(UnsafeCell { value: () }); + impl StaticRWLock { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. /// /// See `RWLock::read`. #[inline] - pub fn read(&'static self) -> StaticRWLockReadGuard { - unsafe { self.inner.read() } - StaticRWLockReadGuard::new(self) + #[unstable = "may be merged with RWLock in the future"] + pub fn read(&'static self) -> LockResult<RWLockReadGuard<'static, ()>> { + unsafe { self.lock.read() } + RWLockReadGuard::new(self, &DUMMY.0) } /// Attempt to acquire this lock with shared read access. /// /// See `RWLock::try_read`. #[inline] - pub fn try_read(&'static self) -> Option<StaticRWLockReadGuard> { - if unsafe { self.inner.try_read() } { - Some(StaticRWLockReadGuard::new(self)) + #[unstable = "may be merged with RWLock in the future"] + pub fn try_read(&'static self) + -> TryLockResult<RWLockReadGuard<'static, ()>> { + if unsafe { self.lock.try_read() } { + Ok(try!(RWLockReadGuard::new(self, &DUMMY.0))) } else { - None + Err(TryLockError::WouldBlock) } } @@ -268,20 +269,23 @@ impl StaticRWLock { /// /// See `RWLock::write`. #[inline] - pub fn write(&'static self) -> StaticRWLockWriteGuard { - unsafe { self.inner.write() } - StaticRWLockWriteGuard::new(self) + #[unstable = "may be merged with RWLock in the future"] + pub fn write(&'static self) -> LockResult<RWLockWriteGuard<'static, ()>> { + unsafe { self.lock.write() } + RWLockWriteGuard::new(self, &DUMMY.0) } /// Attempt to lock this rwlock with exclusive write access. /// /// See `RWLock::try_write`. #[inline] - pub fn try_write(&'static self) -> Option<StaticRWLockWriteGuard> { - if unsafe { self.inner.try_write() } { - Some(StaticRWLockWriteGuard::new(self)) + #[unstable = "may be merged with RWLock in the future"] + pub fn try_write(&'static self) + -> TryLockResult<RWLockWriteGuard<'static, ()>> { + if unsafe { self.lock.try_write() } { + Ok(try!(RWLockWriteGuard::new(self, &DUMMY.0))) } else { - None + Err(TryLockError::WouldBlock) } } @@ -291,70 +295,62 @@ impl StaticRWLock { /// active users of the lock, and this also doesn't prevent any future users /// of this lock. This method is required to be called to not leak memory on /// all platforms. + #[unstable = "may be merged with RWLock in the future"] pub unsafe fn destroy(&'static self) { - self.inner.destroy() + self.lock.destroy() } } impl<'rwlock, T> RWLockReadGuard<'rwlock, T> { - fn new(lock: &RWLock<T>, guard: StaticRWLockReadGuard) - -> RWLockReadGuard<T> { - RWLockReadGuard { __lock: lock, __guard: guard } + fn new(lock: &'rwlock StaticRWLock, data: &'rwlock UnsafeCell<T>) + -> LockResult<RWLockReadGuard<'rwlock, T>> { + poison::map_result(lock.poison.borrow(), |_| { + RWLockReadGuard { + __lock: lock, + __data: data, + __marker: marker::NoSend, + } + }) } } impl<'rwlock, T> RWLockWriteGuard<'rwlock, T> { - fn new(lock: &RWLock<T>, guard: StaticRWLockWriteGuard) - -> RWLockWriteGuard<T> { - RWLockWriteGuard { __lock: lock, __guard: guard } + 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, + __marker: marker::NoSend, + } + }) } } impl<'rwlock, T> Deref<T> for RWLockReadGuard<'rwlock, T> { - fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } } + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } impl<'rwlock, T> Deref<T> for RWLockWriteGuard<'rwlock, T> { - fn deref(&self) -> &T { unsafe { &*self.__lock.data.get() } } + fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } impl<'rwlock, T> DerefMut<T> for RWLockWriteGuard<'rwlock, T> { - fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__lock.data.get() } } -} - -impl StaticRWLockReadGuard { - fn new(lock: &'static StaticRWLock) -> StaticRWLockReadGuard { - let guard = StaticRWLockReadGuard { - lock: &lock.inner, - marker: marker::NoSend, - }; - unsafe { (*lock.poison.get()).borrow().check("rwlock"); } - return guard; - } -} -impl StaticRWLockWriteGuard { - fn new(lock: &'static StaticRWLock) -> StaticRWLockWriteGuard { - unsafe { - let guard = StaticRWLockWriteGuard { - lock: &lock.inner, - marker: marker::NoSend, - poison: (*lock.poison.get()).borrow(), - }; - guard.poison.check("rwlock"); - return guard; - } + fn deref_mut(&mut self) -> &mut T { + unsafe { &mut *self.__data.get() } } } #[unsafe_destructor] -impl Drop for StaticRWLockReadGuard { +impl<'a, T> Drop for RWLockReadGuard<'a, T> { fn drop(&mut self) { - unsafe { self.lock.read_unlock(); } + unsafe { self.__lock.lock.read_unlock(); } } } #[unsafe_destructor] -impl Drop for StaticRWLockWriteGuard { +impl<'a, T> Drop for RWLockWriteGuard<'a, T> { fn drop(&mut self) { - self.poison.done(); - unsafe { self.lock.write_unlock(); } + self.__lock.poison.done(&self.__poison); + unsafe { self.__lock.lock.write_unlock(); } } } @@ -370,19 +366,19 @@ mod tests { #[test] fn smoke() { let l = RWLock::new(()); - drop(l.read()); - drop(l.write()); - drop((l.read(), l.read())); - drop(l.write()); + drop(l.read().unwrap()); + drop(l.write().unwrap()); + drop((l.read().unwrap(), l.read().unwrap())); + drop(l.write().unwrap()); } #[test] fn static_smoke() { static R: StaticRWLock = RWLOCK_INIT; - drop(R.read()); - drop(R.write()); - drop((R.read(), R.read())); - drop(R.write()); + drop(R.read().unwrap()); + drop(R.write().unwrap()); + drop((R.read().unwrap(), R.read().unwrap())); + drop(R.write().unwrap()); unsafe { R.destroy(); } } @@ -396,12 +392,12 @@ mod tests { for _ in range(0, N) { let tx = tx.clone(); Thread::spawn(move|| { - let mut rng = rand::task_rng(); + let mut rng = rand::thread_rng(); for _ in range(0, M) { if rng.gen_weighted_bool(N) { - drop(R.write()); + drop(R.write().unwrap()); } else { - drop(R.read()); + drop(R.read().unwrap()); } } drop(tx); @@ -413,51 +409,47 @@ mod tests { } #[test] - #[should_fail] fn test_rw_arc_poison_wr() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { - let lock = arc2.write(); - assert_eq!(*lock, 2); + let _: Result<uint, _> = Thread::spawn(move|| { + let _lock = arc2.write().unwrap(); + panic!(); }).join(); - let lock = arc.read(); - assert_eq!(*lock, 1); + assert!(arc.read().is_err()); } #[test] - #[should_fail] fn test_rw_arc_poison_ww() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { - let lock = arc2.write(); - assert_eq!(*lock, 2); + let _: Result<uint, _> = Thread::spawn(move|| { + let _lock = arc2.write().unwrap(); + panic!(); }).join(); - let lock = arc.write(); - assert_eq!(*lock, 1); + assert!(arc.write().is_err()); } #[test] fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { - let lock = arc2.read(); - assert_eq!(*lock, 2); + let _: Result<uint, _> = Thread::spawn(move|| { + let _lock = arc2.read().unwrap(); + panic!(); }).join(); - let lock = arc.read(); + let lock = arc.read().unwrap(); assert_eq!(*lock, 1); } #[test] fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RWLock::new(1i)); let arc2 = arc.clone(); - let _ = Thread::spawn(move|| { - let lock = arc2.read(); - assert_eq!(*lock, 2); + let _: Result<uint, _> = Thread::spawn(move|| { + let _lock = arc2.read().unwrap(); + panic!() }).join(); - let lock = arc.write(); + let lock = arc.write().unwrap(); assert_eq!(*lock, 1); } @@ -468,7 +460,7 @@ mod tests { let (tx, rx) = channel(); Thread::spawn(move|| { - let mut lock = arc2.write(); + let mut lock = arc2.write().unwrap(); for _ in range(0u, 10) { let tmp = *lock; *lock = -1; @@ -483,7 +475,7 @@ mod tests { for _ in range(0u, 5) { let arc3 = arc.clone(); children.push(Thread::spawn(move|| { - let lock = arc3.read(); + let lock = arc3.read().unwrap(); assert!(*lock >= 0); })); } @@ -495,7 +487,7 @@ mod tests { // Wait for writer to finish rx.recv().unwrap(); - let lock = arc.read(); + let lock = arc.read().unwrap(); assert_eq!(*lock, 10); } @@ -509,14 +501,14 @@ mod tests { } impl Drop for Unwinder { fn drop(&mut self) { - let mut lock = self.i.write(); + let mut lock = self.i.write().unwrap(); *lock += 1; } } let _u = Unwinder { i: arc2 }; panic!(); }).join(); - let lock = arc.read(); + let lock = arc.read().unwrap(); assert_eq!(*lock, 2); } } diff --git a/src/libstd/sync/semaphore.rs b/src/libstd/sync/semaphore.rs index 784b173b99e..b03c0e08035 100644 --- a/src/libstd/sync/semaphore.rs +++ b/src/libstd/sync/semaphore.rs @@ -68,9 +68,9 @@ impl Semaphore { /// This method will block until the internal count of the semaphore is at /// least 1. pub fn acquire(&self) { - let mut count = self.lock.lock(); + let mut count = self.lock.lock().unwrap(); while *count <= 0 { - self.cvar.wait(&count); + count = self.cvar.wait(count).unwrap(); } *count -= 1; } @@ -80,7 +80,7 @@ impl Semaphore { /// This will increment the number of resources in this semaphore by 1 and /// will notify any pending waiters in `acquire` or `access` if necessary. pub fn release(&self) { - *self.lock.lock() += 1; + *self.lock.lock().unwrap() += 1; self.cvar.notify_one(); } diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index b0325998358..c34fa66d12a 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Abstraction of a task pool for basic parallelism. +//! Abstraction of a thread pool for basic parallelism. use core::prelude::*; @@ -45,9 +45,9 @@ impl<'a> Drop for Sentinel<'a> { } } -/// A task pool used to execute functions in parallel. +/// A thread pool used to execute functions in parallel. /// -/// Spawns `n` worker tasks and replenishes the pool if any worker tasks +/// Spawns `n` worker threads and replenishes the pool if any worker threads /// panic. /// /// # Example @@ -70,34 +70,34 @@ impl<'a> Drop for Sentinel<'a> { /// assert_eq!(rx.iter().take(8u).sum(), 8u); /// ``` pub struct TaskPool { - // How the taskpool communicates with subtasks. + // How the threadpool communicates with subthreads. // - // This is the only such Sender, so when it is dropped all subtasks will + // This is the only such Sender, so when it is dropped all subthreads will // quit. jobs: Sender<Thunk> } impl TaskPool { - /// Spawns a new task pool with `tasks` tasks. + /// Spawns a new thread pool with `threads` threads. /// /// # Panics /// - /// This function will panic if `tasks` is 0. - pub fn new(tasks: uint) -> TaskPool { - assert!(tasks >= 1); + /// This function will panic if `threads` is 0. + pub fn new(threads: uint) -> TaskPool { + assert!(threads >= 1); let (tx, rx) = channel::<Thunk>(); let rx = Arc::new(Mutex::new(rx)); - // Taskpool tasks. - for _ in range(0, tasks) { + // Threadpool threads + for _ in range(0, threads) { spawn_in_pool(rx.clone()); } TaskPool { jobs: tx } } - /// Executes the function `job` on a task in the pool. + /// Executes the function `job` on a thread in the pool. pub fn execute<F>(&self, job: F) where F : FnOnce(), F : Send { @@ -107,14 +107,14 @@ impl TaskPool { fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) { Thread::spawn(move |:| { - // Will spawn a new task on panic unless it is cancelled. + // Will spawn a new thread on panic unless it is cancelled. let sentinel = Sentinel::new(&jobs); loop { let message = { // Only lock jobs for the time it takes // to get a job, not run it. - let lock = jobs.lock(); + let lock = jobs.lock().unwrap(); lock.recv() }; @@ -167,12 +167,12 @@ mod test { let pool = TaskPool::new(TEST_TASKS); - // Panic all the existing tasks. + // Panic all the existing threads. for _ in range(0, TEST_TASKS) { pool.execute(move|| -> () { panic!() }); } - // Ensure new tasks were spawned to compensate. + // Ensure new threads were spawned to compensate. let (tx, rx) = channel(); for _ in range(0, TEST_TASKS) { let tx = tx.clone(); @@ -191,7 +191,7 @@ mod test { let pool = TaskPool::new(TEST_TASKS); let waiter = Arc::new(Barrier::new(TEST_TASKS + 1)); - // Panic all the existing tasks in a bit. + // Panic all the existing threads in a bit. for _ in range(0, TEST_TASKS) { let waiter = waiter.clone(); pool.execute(move|| { diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs index c1aace764fc..d4039fd96ff 100644 --- a/src/libstd/sys/common/backtrace.rs +++ b/src/libstd/sys/common/backtrace.rs @@ -115,10 +115,10 @@ pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { // in theory we can demangle any Unicode code point, but // for simplicity we just catch the common ones. - "$x20" => " ", - "$x27" => "'", - "$x5b" => "[", - "$x5d" => "]" + "$u{20}" => " ", + "$u{27}" => "'", + "$u{5b}" => "[", + "$u{5d}" => "]" ) } else { let idx = match rest.find('$') { diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs index b9dc5f0e398..1ce42aaa175 100644 --- a/src/libstd/sys/common/helper_thread.rs +++ b/src/libstd/sys/common/helper_thread.rs @@ -23,6 +23,7 @@ use prelude::v1::*; use cell::UnsafeCell; +use comm::{channel, Sender, Receiver}; use mem; use rt; use sync::{StaticMutex, StaticCondvar}; @@ -84,7 +85,7 @@ impl<M: Send> Helper<M> { F: FnOnce() -> T, { unsafe { - let _guard = self.lock.lock(); + let _guard = self.lock.lock().unwrap(); if !*self.initialized.get() { let (tx, rx) = channel(); *self.chan.get() = mem::transmute(box tx); @@ -96,7 +97,7 @@ impl<M: Send> Helper<M> { let t = f(); Thread::spawn(move |:| { helper(receive.0, rx, t); - let _g = self.lock.lock(); + let _g = self.lock.lock().unwrap(); *self.shutdown.get() = true; self.cond.notify_one() }).detach(); @@ -112,7 +113,7 @@ impl<M: Send> Helper<M> { /// This is only valid if the worker thread has previously booted pub fn send(&'static self, msg: M) { unsafe { - let _guard = self.lock.lock(); + let _guard = self.lock.lock().unwrap(); // Must send and *then* signal to ensure that the child receives the // message. Otherwise it could wake up and go to sleep before we @@ -128,7 +129,7 @@ impl<M: Send> Helper<M> { // Shut down, but make sure this is done inside our lock to ensure // that we'll always receive the exit signal when the thread // returns. - let guard = self.lock.lock(); + let mut guard = self.lock.lock().unwrap(); // Close the channel by destroying it let chan: Box<Sender<M>> = mem::transmute(*self.chan.get()); @@ -138,7 +139,7 @@ impl<M: Send> Helper<M> { // Wait for the child to exit while !*self.shutdown.get() { - self.cond.wait(&guard); + guard = self.cond.wait(guard).unwrap(); } drop(guard); diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 9ab5077ae79..cb0c5581abd 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -17,6 +17,7 @@ use io::net::addrinfo; use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; use io::{IoResult, IoError}; use libc::{mod, c_char, c_int}; +use c_str::CString; use mem; use num::Int; use ptr::{mod, null, null_mut}; @@ -269,7 +270,7 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, // Collect all the results we found let mut addrs = Vec::new(); let mut rp = res; - while rp.is_not_null() { + while !rp.is_null() { unsafe { let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr), (*rp).ai_addrlen as uint)); @@ -291,6 +292,43 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, } //////////////////////////////////////////////////////////////////////////////// +// get_address_name +//////////////////////////////////////////////////////////////////////////////// + +extern "system" { + fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t, + host: *mut c_char, hostlen: libc::size_t, + serv: *mut c_char, servlen: libc::size_t, + flags: c_int) -> c_int; +} + +const NI_MAXHOST: uint = 1025; + +pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> { + let addr = SocketAddr{ip: addr, port: 0}; + + let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; + let len = addr_to_sockaddr(addr, &mut storage); + + let mut hostbuf = [0 as c_char; NI_MAXHOST]; + + let res = unsafe { + getnameinfo(&storage as *const _ as *const libc::sockaddr, len, + hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, + ptr::null_mut(), 0, + 0) + }; + + if res != 0 { + return Err(last_gai_error(res)); + } + + unsafe { + Ok(CString::new(hostbuf.as_ptr(), false).as_str().unwrap().to_string()) + } +} + +//////////////////////////////////////////////////////////////////////////////// // Timeout helpers // // The read/write functions below are the helpers for reading/writing a socket @@ -669,7 +707,7 @@ impl TcpStream { fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { let ret = Guard { fd: self.fd(), - guard: self.inner.lock.lock(), + guard: self.inner.lock.lock().unwrap(), }; assert!(set_nonblocking(self.fd(), true).is_ok()); ret @@ -808,7 +846,7 @@ impl UdpSocket { fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { let ret = Guard { fd: self.fd(), - guard: self.inner.lock.lock(), + guard: self.inner.lock.lock().unwrap(), }; assert!(set_nonblocking(self.fd(), true).is_ok()); ret diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs index dc21feb17a8..8c76eb1504d 100644 --- a/src/libstd/sys/common/thread_info.rs +++ b/src/libstd/sys/common/thread_info.rs @@ -26,13 +26,13 @@ struct ThreadInfo { thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) } impl ThreadInfo { - fn with<R>(f: |&mut ThreadInfo| -> R) -> R { + fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R { if THREAD_INFO.destroyed() { panic!("Use of std::thread::Thread::current() is not possible after \ the thread's local data has been destroyed"); } - THREAD_INFO.with(|c| { + THREAD_INFO.with(move |c| { if c.borrow().is_none() { *c.borrow_mut() = Some(ThreadInfo { stack_bounds: (0, 0), diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 983d0e5fa14..9e26475f814 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -123,7 +123,7 @@ pub fn write(w: &mut Writer) -> IoResult<()> { try!(writeln!(w, "stack backtrace:")); // 100 lines should be enough const SIZE: uint = 100; - let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()}; + let mut buf: [*mut libc::c_void; SIZE] = unsafe {mem::zeroed()}; let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint}; // skipping the first one as it is write itself @@ -244,7 +244,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { use iter::{Iterator, IteratorExt}; use os; use path::GenericPath; - use ptr::RawPtr; + use ptr::PtrExt; use ptr; use slice::SliceExt; @@ -320,7 +320,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> { // tested if this is required or not. unsafe fn init_state() -> *mut backtrace_state { static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state; - static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256]; + static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256]; if !STATE.is_null() { return STATE } let selfname = if cfg!(target_os = "freebsd") || cfg!(target_os = "dragonfly") { diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs index a4ebcbd25d0..1bb8ed78177 100644 --- a/src/libstd/sys/unix/c.rs +++ b/src/libstd/sys/unix/c.rs @@ -94,7 +94,7 @@ mod select { #[repr(C)] pub struct fd_set { - fds_bits: [i32, ..(FD_SETSIZE / 32)] + fds_bits: [i32; (FD_SETSIZE / 32)] } pub fn fd_set(set: &mut fd_set, fd: i32) { @@ -115,7 +115,7 @@ mod select { #[repr(C)] pub struct fd_set { // FIXME: shouldn't this be a c_ulong? - fds_bits: [libc::uintptr_t, ..(FD_SETSIZE / uint::BITS)] + fds_bits: [libc::uintptr_t; (FD_SETSIZE / uint::BITS)] } pub fn fd_set(set: &mut fd_set, fd: i32) { @@ -168,13 +168,13 @@ mod signal { #[repr(C)] #[cfg(target_word_size = "32")] pub struct sigset_t { - __val: [libc::c_ulong, ..32], + __val: [libc::c_ulong; 32], } #[repr(C)] #[cfg(target_word_size = "64")] pub struct sigset_t { - __val: [libc::c_ulong, ..16], + __val: [libc::c_ulong; 16], } } @@ -211,15 +211,15 @@ mod signal { pub sa_handler: extern fn(libc::c_int), pub sa_mask: sigset_t, sa_restorer: *mut libc::c_void, - sa_resv: [libc::c_int, ..1], + sa_resv: [libc::c_int; 1], } - impl ::kinds::Send for sigaction { } - impl ::kinds::Sync for sigaction { } + unsafe impl ::kinds::Send for sigaction { } + unsafe impl ::kinds::Sync for sigaction { } #[repr(C)] pub struct sigset_t { - __val: [libc::c_ulong, ..32], + __val: [libc::c_ulong; 32], } } @@ -244,7 +244,7 @@ mod signal { #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] #[repr(C)] pub struct sigset_t { - bits: [u32, ..4], + bits: [u32; 4], } // This structure has more fields, but we're not all that interested in diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index d537579d453..e3e0b279c12 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -371,7 +371,7 @@ mod tests { let mut writer = FileDesc::new(writer, true); writer.write(b"test").ok().unwrap(); - let mut buf = [0u8, ..4]; + let mut buf = [0u8; 4]; match reader.read(&mut buf) { Ok(4) => { assert_eq!(buf[0], 't' as u8); diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 15dad810756..4199cbc1bb9 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -56,6 +56,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module @@ -109,6 +110,8 @@ pub fn decode_error(errno: i32) -> IoError { "file descriptor is not a TTY"), libc::ETIMEDOUT => (io::TimedOut, "operation timed out"), libc::ECANCELED => (io::TimedOut, "operation aborted"), + libc::consts::os::posix88::EEXIST => + (io::PathAlreadyExists, "path already exists"), // These two constants can have the same value on some systems, // but different values on others, so we can't use a match diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index a221a6bc15b..6d145e47516 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -101,7 +101,7 @@ pub fn error_string(errno: i32) -> String { } } - let mut buf = [0 as c_char, ..TMPBUF_SZ]; + let mut buf = [0 as c_char; TMPBUF_SZ]; let p = buf.as_mut_ptr(); unsafe { @@ -114,7 +114,7 @@ pub fn error_string(errno: i32) -> String { } pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { - let mut fds = [0, ..2]; + let mut fds = [0; 2]; if libc::pipe(fds.as_mut_ptr()) == 0 { Ok((FileDesc::new(fds[0], true), FileDesc::new(fds[1], true))) } else { @@ -125,7 +125,7 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { pub fn getcwd() -> IoResult<Path> { use c_str::CString; - let mut buf = [0 as c_char, ..BUF_BYTES]; + let mut buf = [0 as c_char; BUF_BYTES]; unsafe { if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { Err(IoError::last_error()) diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 6954866257e..e46814ef4a2 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -145,7 +145,7 @@ impl UnixStream { fn lock_nonblocking<'a>(&'a self) -> Guard<'a> { let ret = Guard { fd: self.fd(), - guard: unsafe { self.inner.lock.lock() }, + guard: unsafe { self.inner.lock.lock().unwrap() }, }; assert!(set_nonblocking(self.fd(), true).is_ok()); ret diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index a11fe3487a8..af09bf4fbd0 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -121,7 +121,7 @@ impl Process { let p = Process{ pid: pid }; drop(output); - let mut bytes = [0, ..8]; + let mut bytes = [0; 8]; return match input.read(&mut bytes) { Ok(8) => { assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)), @@ -196,7 +196,7 @@ impl Process { // up /dev/null into that file descriptor. Otherwise, the first file // descriptor opened up in the child would be numbered as one of the // stdio file descriptors, which is likely to wreak havoc. - let setup = |src: Option<P>, dst: c_int| { + let setup = |&: src: Option<P>, dst: c_int| { let src = match src { None => { let flags = if dst == libc::STDIN_FILENO { @@ -349,7 +349,7 @@ impl Process { // handler we're going to start receiving signals. fn register_sigchld() -> (libc::c_int, c::sigaction) { unsafe { - let mut pipes = [0, ..2]; + let mut pipes = [0; 2]; assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0); set_nonblocking(pipes[0], true).ok().unwrap(); set_nonblocking(pipes[1], true).ok().unwrap(); @@ -483,7 +483,7 @@ impl Process { fn drain(fd: libc::c_int) -> bool { let mut ret = false; loop { - let mut buf = [0u8, ..1]; + let mut buf = [0u8; 1]; match unsafe { libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len() as libc::size_t) diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index bcbbb8766b7..95ab9b459d6 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -184,12 +184,12 @@ mod imp { #[cfg(target_word_size = "32")] #[repr(C)] pub struct sigset_t { - __val: [libc::c_ulong, ..32], + __val: [libc::c_ulong; 32], } #[cfg(target_word_size = "64")] #[repr(C)] pub struct sigset_t { - __val: [libc::c_ulong, ..16], + __val: [libc::c_ulong; 16], } #[repr(C)] diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs index 007826b4b9d..77c5582d8a4 100644 --- a/src/libstd/sys/unix/sync.rs +++ b/src/libstd/sys/unix/sync.rs @@ -86,30 +86,30 @@ mod os { #[repr(C)] pub struct pthread_mutex_t { __sig: libc::c_long, - __opaque: [u8, ..__PTHREAD_MUTEX_SIZE__], + __opaque: [u8; __PTHREAD_MUTEX_SIZE__], } #[repr(C)] pub struct pthread_cond_t { __sig: libc::c_long, - __opaque: [u8, ..__PTHREAD_COND_SIZE__], + __opaque: [u8; __PTHREAD_COND_SIZE__], } #[repr(C)] pub struct pthread_rwlock_t { __sig: libc::c_long, - __opaque: [u8, ..__PTHREAD_RWLOCK_SIZE__], + __opaque: [u8; __PTHREAD_RWLOCK_SIZE__], } pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __sig: _PTHREAD_MUTEX_SIG_INIT, - __opaque: [0, ..__PTHREAD_MUTEX_SIZE__], + __opaque: [0; __PTHREAD_MUTEX_SIZE__], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __sig: _PTHREAD_COND_SIG_INIT, - __opaque: [0, ..__PTHREAD_COND_SIZE__], + __opaque: [0; __PTHREAD_COND_SIZE__], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __sig: _PTHREAD_RWLOCK_SIG_INIT, - __opaque: [0, ..__PTHREAD_RWLOCK_SIZE__], + __opaque: [0; __PTHREAD_RWLOCK_SIZE__], }; } @@ -145,30 +145,30 @@ mod os { #[repr(C)] pub struct pthread_mutex_t { __align: libc::c_longlong, - size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T], + size: [u8; __SIZEOF_PTHREAD_MUTEX_T], } #[repr(C)] pub struct pthread_cond_t { __align: libc::c_longlong, - size: [u8, ..__SIZEOF_PTHREAD_COND_T], + size: [u8; __SIZEOF_PTHREAD_COND_T], } #[repr(C)] pub struct pthread_rwlock_t { __align: libc::c_longlong, - size: [u8, ..__SIZEOF_PTHREAD_RWLOCK_T], + size: [u8; __SIZEOF_PTHREAD_RWLOCK_T], } pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { __align: 0, - size: [0, ..__SIZEOF_PTHREAD_MUTEX_T], + size: [0; __SIZEOF_PTHREAD_MUTEX_T], }; pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t { __align: 0, - size: [0, ..__SIZEOF_PTHREAD_COND_T], + size: [0; __SIZEOF_PTHREAD_COND_T], }; pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t { __align: 0, - size: [0, ..__SIZEOF_PTHREAD_RWLOCK_T], + size: [0; __SIZEOF_PTHREAD_RWLOCK_T], }; } #[cfg(target_os = "android")] @@ -187,7 +187,7 @@ mod os { writerThreadId: libc::c_int, pendingReaders: libc::c_int, pendingWriters: libc::c_int, - reserved: [*mut libc::c_void, ..4], + reserved: [*mut libc::c_void; 4], } pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t { @@ -203,6 +203,6 @@ mod os { writerThreadId: 0, pendingReaders: 0, pendingWriters: 0, - reserved: [0 as *mut _, ..4], + reserved: [0 as *mut _; 4], }; } diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs index 4afe13d8735..afa77140d13 100644 --- a/src/libstd/sys/unix/timer.rs +++ b/src/libstd/sys/unix/timer.rs @@ -120,9 +120,9 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { // signals the first requests in the queue, possible re-enqueueing it. fn signal(active: &mut Vec<Box<Inner>>, dead: &mut Vec<(uint, Box<Inner>)>) { - let mut timer = match active.remove(0) { - Some(timer) => timer, None => return - }; + if active.is_empty() { return } + + let mut timer = active.remove(0); let mut cb = timer.cb.take().unwrap(); cb.call(); if timer.repeat { @@ -178,7 +178,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { Ok(RemoveTimer(id, ack)) => { match dead.iter().position(|&(i, _)| id == i) { Some(i) => { - let (_, i) = dead.remove(i).unwrap(); + let (_, i) = dead.remove(i); ack.send(i).unwrap(); continue } @@ -186,7 +186,7 @@ fn helper(input: libc::c_int, messages: Receiver<Req>, _: ()) { } let i = active.iter().position(|i| i.id == id); let i = i.expect("no timer found"); - let t = active.remove(i).unwrap(); + let t = active.remove(i); ack.send(t).unwrap(); } Err(..) => break diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 42c8f7705e1..319a458087b 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -68,7 +68,7 @@ const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664; struct SYMBOL_INFO { SizeOfStruct: libc::c_ulong, TypeIndex: libc::c_ulong, - Reserved: [u64, ..2], + Reserved: [u64; 2], Index: libc::c_ulong, Size: libc::c_ulong, ModBase: u64, @@ -83,7 +83,7 @@ struct SYMBOL_INFO { // note that windows has this as 1, but it basically just means that // the name is inline at the end of the struct. For us, we just bump // the struct size up to MAX_SYM_NAME. - Name: [libc::c_char, ..MAX_SYM_NAME], + Name: [libc::c_char; MAX_SYM_NAME], } @@ -108,10 +108,10 @@ struct STACKFRAME64 { AddrStack: ADDRESS64, AddrBStore: ADDRESS64, FuncTableEntry: *mut libc::c_void, - Params: [u64, ..4], + Params: [u64; 4], Far: libc::BOOL, Virtual: libc::BOOL, - Reserved: [u64, ..3], + Reserved: [u64; 3], KdHelp: KDHELP64, } @@ -127,7 +127,7 @@ struct KDHELP64 { KiUserExceptionDispatcher: u64, StackBase: u64, StackLimit: u64, - Reserved: [u64, ..5], + Reserved: [u64; 5], } #[cfg(target_arch = "x86")] @@ -162,7 +162,7 @@ mod arch { EFlags: libc::DWORD, Esp: libc::DWORD, SegSs: libc::DWORD, - ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION], + ExtendedRegisters: [u8; MAXIMUM_SUPPORTED_EXTENSION], } #[repr(C)] @@ -174,7 +174,7 @@ mod arch { ErrorSelector: libc::DWORD, DataOffset: libc::DWORD, DataSelector: libc::DWORD, - RegisterArea: [u8, ..80], + RegisterArea: [u8; 80], Cr0NpxState: libc::DWORD, } @@ -198,7 +198,7 @@ mod arch { #[repr(C)] pub struct CONTEXT { - _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte P1Home: DWORDLONG, P2Home: DWORDLONG, P3Home: DWORDLONG, @@ -245,7 +245,7 @@ mod arch { FltSave: FLOATING_SAVE_AREA, - VectorRegister: [M128A, .. 26], + VectorRegister: [M128A; 26], VectorControl: DWORDLONG, DebugControl: DWORDLONG, @@ -257,15 +257,15 @@ mod arch { #[repr(C)] pub struct M128A { - _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte Low: c_ulonglong, High: c_longlong } #[repr(C)] pub struct FLOATING_SAVE_AREA { - _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte - _Dummy: [u8, ..512] // FIXME: Fill this out + _align_hack: [simd::u64x2; 0], // FIXME align on 16-byte + _Dummy: [u8; 512] // FIXME: Fill this out } pub fn init_frame(frame: &mut super::STACKFRAME64, diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index d1177776dd8..1ee57434fb9 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -43,8 +43,8 @@ pub const WSA_WAIT_FAILED: libc::DWORD = libc::consts::os::extra::WAIT_FAILED; pub struct WSADATA { pub wVersion: libc::WORD, pub wHighVersion: libc::WORD, - pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1], + pub szDescription: [u8; WSADESCRIPTION_LEN + 1], + pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], pub iMaxSockets: u16, pub iMaxUdpDg: u16, pub lpVendorInfo: *mut u8, @@ -57,8 +57,8 @@ pub struct WSADATA { pub iMaxSockets: u16, pub iMaxUdpDg: u16, pub lpVendorInfo: *mut u8, - pub szDescription: [u8, ..WSADESCRIPTION_LEN + 1], - pub szSystemStatus: [u8, ..WSASYS_STATUS_LEN + 1], + pub szDescription: [u8; WSADESCRIPTION_LEN + 1], + pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], } pub type LPWSADATA = *mut WSADATA; @@ -66,7 +66,7 @@ pub type LPWSADATA = *mut WSADATA; #[repr(C)] pub struct WSANETWORKEVENTS { pub lNetworkEvents: libc::c_long, - pub iErrorCode: [libc::c_int, ..FD_MAX_EVENTS], + pub iErrorCode: [libc::c_int; FD_MAX_EVENTS], } pub type LPWSANETWORKEVENTS = *mut WSANETWORKEVENTS; @@ -76,7 +76,7 @@ pub type WSAEVENT = libc::HANDLE; #[repr(C)] pub struct fd_set { fd_count: libc::c_uint, - fd_array: [libc::SOCKET, ..FD_SETSIZE], + fd_array: [libc::SOCKET; FD_SETSIZE], } pub fn fd_set(set: &mut fd_set, s: libc::SOCKET) { @@ -131,9 +131,9 @@ extern "system" { pub mod compat { use intrinsics::{atomic_store_relaxed, transmute}; - use iter::IteratorExt; use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID}; use prelude::v1::*; + use c_str::ToCStr; extern "system" { fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE; diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 632261f0ad9..523d60c71aa 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -265,8 +265,8 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> { { let filename = os::truncate_utf16_at_nul(&wfd.cFileName); match String::from_utf16(filename) { - Some(filename) => paths.push(Path::new(filename)), - None => { + Ok(filename) => paths.push(Path::new(filename)), + Err(..) => { assert!(libc::FindClose(find_handle) != 0); return Err(IoError { kind: io::InvalidInput, diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 94f5822ccea..c354e7b3ece 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -24,6 +24,7 @@ use num; use mem; use io::{mod, IoResult, IoError}; use sync::{Once, ONCE_INIT}; +use comm::Sender; macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( static $name: Helper<$m> = Helper { @@ -58,6 +59,7 @@ pub mod udp; pub mod addrinfo { pub use sys_common::net::get_host_addresses; + pub use sys_common::net::get_address_name; } // FIXME: move these to c module @@ -122,6 +124,8 @@ pub fn decode_error(errno: i32) -> IoError { "invalid handle provided to function"), libc::ERROR_NOTHING_TO_TERMINATE => (io::InvalidInput, "no process to kill"), + libc::ERROR_ALREADY_EXISTS => + (io::PathAlreadyExists, "path already exists"), // libuv maps this error code to EISDIR. we do too. if it is found // to be incorrect, we can add in some more machinery to only diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 159512525d8..dfdee0e0385 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -17,14 +17,14 @@ use prelude::v1::*; use fmt; use io::{IoResult, IoError}; -use libc::{c_int, c_char, c_void}; +use iter::repeat; +use libc::{c_int, c_void}; use libc; use os; use path::BytesContainer; use ptr; -use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; -use sys::fs::FileDesc; use slice; +use sys::fs::FileDesc; use os::TMPBUF_SZ; use libc::types::os::arch::extra::DWORD; @@ -80,7 +80,7 @@ pub fn error_string(errnum: i32) -> String { // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT) let langId = 0x0800 as DWORD; - let mut buf = [0 as WCHAR, ..TMPBUF_SZ]; + let mut buf = [0 as WCHAR; TMPBUF_SZ]; unsafe { let res = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | @@ -99,8 +99,9 @@ pub fn error_string(errnum: i32) -> String { let msg = String::from_utf16(truncate_utf16_at_nul(&buf)); match msg { - Some(msg) => format!("OS Error {}: {}", errnum, msg), - None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum), + Ok(msg) => format!("OS Error {}: {}", errnum, msg), + Err(..) => format!("OS Error {} (FormatMessageW() returned \ + invalid UTF-16)", errnum), } } } @@ -111,7 +112,7 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { // fully understand. Here we explicitly make the pipe non-inheritable, // which means to pass it to a subprocess they need to be duplicated // first, as in std::run. - let mut fds = [0, ..2]; + let mut fds = [0; 2]; match libc::pipe(fds.as_mut_ptr(), 1024 as ::libc::c_uint, (libc::O_BINARY | libc::O_NOINHERIT) as c_int) { 0 => { @@ -123,13 +124,15 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> { } } -pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String> { +pub fn fill_utf16_buf_and_decode<F>(mut f: F) -> Option<String> where + F: FnMut(*mut u16, DWORD) -> DWORD, +{ unsafe { let mut n = TMPBUF_SZ as DWORD; let mut res = None; let mut done = false; while !done { - let mut buf = Vec::from_elem(n as uint, 0u16); + let mut buf: Vec<u16> = repeat(0u16).take(n as uint).collect(); let k = f(buf.as_mut_ptr(), n); if k == (0 as DWORD) { done = true; @@ -147,7 +150,7 @@ pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String // We want to explicitly catch the case when the // closure returned invalid UTF-16, rather than // set `res` to None and continue. - let s = String::from_utf16(sub) + let s = String::from_utf16(sub).ok() .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16"); res = Some(s) } @@ -161,7 +164,7 @@ pub fn getcwd() -> IoResult<Path> { use libc::GetCurrentDirectoryW; use io::OtherIoError; - let mut buf = [0 as u16, ..BUF_BYTES]; + let mut buf = [0 as u16; BUF_BYTES]; unsafe { if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD { return Err(IoError::last_error()); @@ -169,8 +172,8 @@ pub fn getcwd() -> IoResult<Path> { } match String::from_utf16(truncate_utf16_at_nul(&buf)) { - Some(ref cwd) => Ok(Path::new(cwd)), - None => Err(IoError { + Ok(ref cwd) => Ok(Path::new(cwd)), + Err(..) => Err(IoError { kind: OtherIoError, desc: "GetCurrentDirectoryW returned invalid UTF-16", detail: None, diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index f99995eb028..cb99a886ce4 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -12,7 +12,7 @@ use prelude::v1::*; use libc::{pid_t, c_void, c_int}; use libc; -use c_str::CString; +use c_str::{CString, ToCStr}; use io; use mem; use os; @@ -163,7 +163,7 @@ impl Process { // Similarly to unix, we don't actually leave holes for the stdio file // descriptors, but rather open up /dev/null equivalents. These // equivalents are drawn from libuv's windows process spawning. - let set_fd = |fd: &Option<P>, slot: &mut HANDLE, + let set_fd = |&: fd: &Option<P>, slot: &mut HANDLE, is_stdin: bool| { match *fd { None => { @@ -467,6 +467,7 @@ fn free_handle(handle: *mut ()) { #[cfg(test)] mod tests { + use c_str::ToCStr; #[test] fn test_make_command_line() { diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs index bdf2e0bccb1..e8b447022cb 100644 --- a/src/libstd/sys/windows/stack_overflow.rs +++ b/src/libstd/sys/windows/stack_overflow.rs @@ -90,7 +90,7 @@ pub struct EXCEPTION_RECORD { pub ExceptionRecord: *mut EXCEPTION_RECORD, pub ExceptionAddress: LPVOID, pub NumberParameters: DWORD, - pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS] + pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS] } pub struct EXCEPTION_POINTERS { diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs index 3df0debff51..485dc251050 100644 --- a/src/libstd/sys/windows/timer.rs +++ b/src/libstd/sys/windows/timer.rs @@ -21,16 +21,17 @@ //! the other two implementations of timers with nothing *that* new showing up. use self::Req::*; +use prelude::v1::*; use libc; use ptr; use comm; +use comm::{channel, Sender, Receiver}; +use io::IoResult; use sys::c; use sys::fs::FileDesc; use sys_common::helper_thread::Helper; -use prelude::v1::*; -use io::IoResult; helper_init! { static HELPER: Helper<Req> } diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs index dfa3440067a..7591025d76d 100644 --- a/src/libstd/sys/windows/tty.rs +++ b/src/libstd/sys/windows/tty.rs @@ -27,17 +27,18 @@ use prelude::v1::*; -use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; -use super::c::{ERROR_ILLEGAL_CHARACTER}; -use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; -use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; -use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; +use io::{mod, IoError, IoResult, MemReader}; +use iter::repeat; +use libc::types::os::arch::extra::LPCVOID; use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID}; use libc::{get_osfhandle, CloseHandle}; -use libc::types::os::arch::extra::LPCVOID; -use io::{mod, IoError, IoResult, MemReader}; use ptr; use str::from_utf8; +use super::c::{ENABLE_ECHO_INPUT, ENABLE_EXTENDED_FLAGS}; +use super::c::{ENABLE_INSERT_MODE, ENABLE_LINE_INPUT}; +use super::c::{ENABLE_PROCESSED_INPUT, ENABLE_QUICK_EDIT_MODE}; +use super::c::{ERROR_ILLEGAL_CHARACTER}; +use super::c::{ReadConsoleW, WriteConsoleW, GetConsoleMode, SetConsoleMode}; fn invalid_encoding() -> IoError { IoError { @@ -90,7 +91,7 @@ impl TTY { pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { // Read more if the buffer is empty if self.utf8.eof() { - let mut utf16 = Vec::from_elem(0x1000, 0u16); + let mut utf16: Vec<u16> = repeat(0u16).take(0x1000).collect(); let mut num: DWORD = 0; match unsafe { ReadConsoleW(self.handle, utf16.as_mut_ptr() as LPVOID, @@ -102,8 +103,8 @@ impl TTY { }; utf16.truncate(num as uint); let utf8 = match String::from_utf16(utf16.as_slice()) { - Some(utf8) => utf8.into_bytes(), - None => return Err(invalid_encoding()), + Ok(utf8) => utf8.into_bytes(), + Err(..) => return Err(invalid_encoding()), }; self.utf8 = MemReader::new(utf8); } diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 5c9e6153afb..9a6fcab6a88 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -313,7 +313,7 @@ impl Thread { /// Spawn a new joinable thread, returning a `JoinGuard` for it. /// - /// The join guard can be used to explicitly join the child thead (via + /// The join guard can be used to explicitly join the child thread (via /// `join`), returning `Result<T>`, or it will implicitly join the child /// upon being dropped. To detach the child, allowing it to outlive the /// current thread, use `detach`. See the module documentation for additional details. @@ -334,6 +334,7 @@ impl Thread { } /// Determines whether the current thread is panicking. + #[inline] pub fn panicking() -> bool { unwind::panicking() } @@ -349,9 +350,9 @@ impl Thread { // or futuxes, and in either case may allow spurious wakeups. pub fn park() { let thread = Thread::current(); - let mut guard = thread.inner.lock.lock(); + let mut guard = thread.inner.lock.lock().unwrap(); while !*guard { - thread.inner.cvar.wait(&guard); + guard = thread.inner.cvar.wait(guard).unwrap(); } *guard = false; } @@ -360,7 +361,7 @@ impl Thread { /// /// See the module doc for more detail. pub fn unpark(&self) { - let mut guard = self.inner.lock.lock(); + let mut guard = self.inner.lock.lock().unwrap(); if !*guard { *guard = true; self.inner.cvar.notify_one(); diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index 6cd26a366ae..4950337b9af 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -189,22 +189,7 @@ macro_rules! __thread_local_inner { } }; - #[cfg(all(stage0, not(any(target_os = "macos", target_os = "linux"))))] - const INIT: ::std::thread_local::KeyInner<$t> = { - unsafe extern fn __destroy(ptr: *mut u8) { - ::std::thread_local::destroy_value::<$t>(ptr); - } - - ::std::thread_local::KeyInner { - inner: ::std::cell::UnsafeCell { value: $init }, - os: ::std::thread_local::OsStaticKey { - inner: ::std::thread_local::OS_INIT_INNER, - dtor: ::std::option::Option::Some(__destroy), - }, - } - }; - - #[cfg(all(not(stage0), not(any(target_os = "macos", target_os = "linux"))))] + #[cfg(all(not(any(target_os = "macos", target_os = "linux"))))] const INIT: ::std::thread_local::KeyInner<$t> = { unsafe extern fn __destroy(ptr: *mut u8) { ::std::thread_local::destroy_value::<$t>(ptr); @@ -240,13 +225,18 @@ impl<T: 'static> Key<T> { unsafe { let slot = slot.get().expect("cannot access a TLS value during or \ after it is destroyed"); - if (*slot.get()).is_none() { - *slot.get() = Some((self.init)()); - } - f((*slot.get()).as_ref().unwrap()) + f(match *slot.get() { + Some(ref inner) => inner, + None => self.init(slot), + }) } } + unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T { + *slot.get() = Some((self.init)()); + (*slot.get()).as_ref().unwrap() + } + /// Test this TLS key to determine whether its value has been destroyed for /// the current thread or not. /// @@ -341,16 +331,10 @@ mod imp { // *should* be the case that this loop always terminates because we // provide the guarantee that a TLS key cannot be set after it is // flagged for destruction. - #[cfg(not(stage0))] static DTORS: os::StaticKey = os::StaticKey { inner: os::INIT_INNER, dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)), }; - #[cfg(stage0)] - static DTORS: os::StaticKey = os::StaticKey { - inner: os::INIT_INNER, - dtor: Some(run_dtors), - }; type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; if DTORS.get().is_null() { let v: Box<List> = box Vec::new(); diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index a06048aa706..a2e2bd43849 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -62,10 +62,10 @@ pub struct Key<T> { #[doc(hidden)] pub inner: KeyInner<T> } #[macro_export] macro_rules! scoped_thread_local { (static $name:ident: $t:ty) => ( - __scoped_thread_local_inner!(static $name: $t) + __scoped_thread_local_inner!(static $name: $t); ); (pub static $name:ident: $t:ty) => ( - __scoped_thread_local_inner!(pub static $name: $t) + __scoped_thread_local_inner!(pub static $name: $t); ); } @@ -240,6 +240,8 @@ mod tests { use cell::Cell; use prelude::v1::*; + scoped_thread_local!(static FOO: uint); + #[test] fn smoke() { scoped_thread_local!(static BAR: uint); @@ -264,4 +266,16 @@ mod tests { }); }); } + + #[test] + fn scope_item_allowed() { + assert!(!FOO.is_set()); + FOO.set(&1, || { + assert!(FOO.is_set()); + FOO.with(|slot| { + assert_eq!(*slot, 1); + }); + }); + assert!(!FOO.is_set()); + } } diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index f7351c9580f..51564b53976 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -262,20 +262,6 @@ impl Duration { } } -// NOTE(stage0): Remove impl after a snapshot -#[cfg(stage0)] -impl Neg<Duration> for Duration { - #[inline] - fn neg(&self) -> Duration { - if self.nanos == 0 { - Duration { secs: -self.secs, nanos: 0 } - } else { - Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos } - } - } -} - -#[cfg(not(stage0))] // NOTE(stage0): Remove cfg after a snapshot impl Neg<Duration> for Duration { #[inline] fn neg(self) -> Duration { |
