Auto merge of #33699 - alexcrichton:stabilize-1.10, r=aturon

std: Stabilize APIs for the 1.10 release

This commit applies the FCP decisions made by the libs team for the 1.10 cycle,
including both new stabilizations and deprecations. Specifically, the list of
APIs is:

Stabilized:

* `os::windows::fs::OpenOptionsExt::access_mode`
* `os::windows::fs::OpenOptionsExt::share_mode`
* `os::windows::fs::OpenOptionsExt::custom_flags`
* `os::windows::fs::OpenOptionsExt::attributes`
* `os::windows::fs::OpenOptionsExt::security_qos_flags`
* `os::unix::fs::OpenOptionsExt::custom_flags`
* `sync::Weak::new`
* `Default for sync::Weak`
* `panic::set_hook`
* `panic::take_hook`
* `panic::PanicInfo`
* `panic::PanicInfo::payload`
* `panic::PanicInfo::location`
* `panic::Location`
* `panic::Location::file`
* `panic::Location::line`
* `ffi::CStr::from_bytes_with_nul`
* `ffi::CStr::from_bytes_with_nul_unchecked`
* `ffi::FromBytesWithNulError`
* `fs::Metadata::modified`
* `fs::Metadata::accessed`
* `fs::Metadata::created`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange`
* `sync::atomic::Atomic{Usize,Isize,Bool,Ptr}::compare_exchange_weak`
* `collections::{btree,hash}_map::{Occupied,Vacant,}Entry::key`
* `os::unix::net::{UnixStream, UnixListener, UnixDatagram, SocketAddr}`
* `SocketAddr::is_unnamed`
* `SocketAddr::as_pathname`
* `UnixStream::connect`
* `UnixStream::pair`
* `UnixStream::try_clone`
* `UnixStream::local_addr`
* `UnixStream::peer_addr`
* `UnixStream::set_read_timeout`
* `UnixStream::set_write_timeout`
* `UnixStream::read_timeout`
* `UnixStream::write_Timeout`
* `UnixStream::set_nonblocking`
* `UnixStream::take_error`
* `UnixStream::shutdown`
* Read/Write/RawFd impls for `UnixStream`
* `UnixListener::bind`
* `UnixListener::accept`
* `UnixListener::try_clone`
* `UnixListener::local_addr`
* `UnixListener::set_nonblocking`
* `UnixListener::take_error`
* `UnixListener::incoming`
* RawFd impls for `UnixListener`
* `UnixDatagram::bind`
* `UnixDatagram::unbound`
* `UnixDatagram::pair`
* `UnixDatagram::connect`
* `UnixDatagram::try_clone`
* `UnixDatagram::local_addr`
* `UnixDatagram::peer_addr`
* `UnixDatagram::recv_from`
* `UnixDatagram::recv`
* `UnixDatagram::send_to`
* `UnixDatagram::send`
* `UnixDatagram::set_read_timeout`
* `UnixDatagram::set_write_timeout`
* `UnixDatagram::read_timeout`
* `UnixDatagram::write_timeout`
* `UnixDatagram::set_nonblocking`
* `UnixDatagram::take_error`
* `UnixDatagram::shutdown`
* RawFd impls for `UnixDatagram`
* `{BTree,Hash}Map::values_mut`
* `<[_]>::binary_search_by_key`

Deprecated:

* `StaticCondvar` - this, and all other static synchronization primitives
                    below, are usable today through the lazy-static crate on
                    stable Rust today. Additionally, we'd like the non-static
                    versions to be directly usable in a static context one day,
                    so they're unlikely to be the final forms of the APIs in any
                    case.
* `CONDVAR_INIT`
* `StaticMutex`
* `MUTEX_INIT`
* `StaticRwLock`
* `RWLOCK_INIT`
* `iter::Peekable::is_empty`

Closes #27717
Closes #27720
Closes #30014
Closes #30425
Closes #30449
Closes #31190
Closes #31399
Closes #31767
Closes #32111
Closes #32281
Closes #32312
Closes #32551
Closes #33018
This commit is contained in:
bors 2016-05-25 20:36:09 -07:00
commit d5759a3417
37 changed files with 567 additions and 494 deletions

View File

@ -592,6 +592,31 @@ impl<T: ?Sized> Drop for Arc<T> {
}
}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
///
/// # Examples
///
/// ```
/// use std::sync::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// ```
#[stable(feature = "downgraded_weak", since = "1.10.0")]
pub fn new() -> Weak<T> {
unsafe {
Weak { ptr: Shared::new(Box::into_raw(box ArcInner {
strong: atomic::AtomicUsize::new(0),
weak: atomic::AtomicUsize::new(1),
data: uninitialized(),
}))}
}
}
}
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
@ -682,6 +707,13 @@ impl<T: ?Sized> Clone for Weak<T> {
}
}
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
fn default() -> Weak<T> {
Weak::new()
}
}
#[stable(feature = "arc_weak", since = "1.4.0")]
impl<T: ?Sized> Drop for Weak<T> {
/// Drops the `Weak<T>`.
@ -907,35 +939,6 @@ impl<T> From<T> for Arc<T> {
}
}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
///
/// # Examples
///
/// ```
/// #![feature(downgraded_weak)]
///
/// use std::sync::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// ```
#[unstable(feature = "downgraded_weak",
reason = "recently added",
issue = "30425")]
pub fn new() -> Weak<T> {
unsafe {
Weak { ptr: Shared::new(Box::into_raw(box ArcInner {
strong: atomic::AtomicUsize::new(0),
weak: atomic::AtomicUsize::new(1),
data: uninitialized(),
}))}
}
}
}
#[cfg(test)]
mod tests {
use std::clone::Clone;

View File

@ -90,7 +90,6 @@
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(unsize)]
#![feature(extended_compare_and_swap)]
#![cfg_attr(not(test), feature(raw, fn_traits, placement_new_protocol))]
#![cfg_attr(test, feature(test, box_heap))]

View File

@ -720,6 +720,33 @@ impl<T: ?Sized> !marker::Sync for Weak<T> {}
#[unstable(feature = "coerce_unsized", issue = "27732")]
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
///
/// # Examples
///
/// ```
/// use std::rc::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// ```
#[stable(feature = "downgraded_weak", since = "1.10.0")]
pub fn new() -> Weak<T> {
unsafe {
Weak {
ptr: Shared::new(Box::into_raw(box RcBox {
strong: Cell::new(0),
weak: Cell::new(1),
value: uninitialized(),
})),
}
}
}
}
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
@ -823,34 +850,10 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
}
}
impl<T> Weak<T> {
/// Constructs a new `Weak<T>` without an accompanying instance of T.
///
/// This allocates memory for T, but does not initialize it. Calling
/// Weak<T>::upgrade() on the return value always gives None.
///
/// # Examples
///
/// ```
/// #![feature(downgraded_weak)]
///
/// use std::rc::Weak;
///
/// let empty: Weak<i64> = Weak::new();
/// ```
#[unstable(feature = "downgraded_weak",
reason = "recently added",
issue="30425")]
pub fn new() -> Weak<T> {
unsafe {
Weak {
ptr: Shared::new(Box::into_raw(box RcBox {
strong: Cell::new(0),
weak: Cell::new(1),
value: uninitialized(),
})),
}
}
#[stable(feature = "downgraded_weak", since = "1.10.0")]
impl<T> Default for Weak<T> {
fn default() -> Weak<T> {
Weak::new()
}
}

View File

@ -286,7 +286,7 @@ pub struct Values<'a, K: 'a, V: 'a> {
}
/// A mutable iterator over a BTreeMap's values.
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>,
}
@ -1144,7 +1144,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> {
}
}
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;
@ -1157,14 +1157,14 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
}
}
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> {
fn next_back(&mut self) -> Option<&'a mut V> {
self.inner.next_back().map(|(_, v)| v)
}
}
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
fn len(&self) -> usize {
self.inner.len()
@ -1575,7 +1575,6 @@ impl<K, V> BTreeMap<K, V> {
/// Basic usage:
///
/// ```
/// # #![feature(map_values_mut)]
/// use std::collections::BTreeMap;
///
/// let mut a = BTreeMap::new();
@ -1590,8 +1589,8 @@ impl<K, V> BTreeMap<K, V> {
/// assert_eq!(values, [String::from("hello!"),
/// String::from("goodbye!")]);
/// ```
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
pub fn values_mut<'a>(&'a mut self) -> ValuesMut<'a, K, V> {
#[stable(feature = "map_values_mut", since = "1.10.0")]
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
ValuesMut { inner: self.iter_mut() }
}
@ -1656,7 +1655,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
}
/// Returns a reference to this entry's key.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
match *self {
Occupied(ref entry) => entry.key(),
@ -1668,7 +1667,7 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
/// Gets a reference to the key that would be used when inserting a value
/// through the VacantEntry.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
&self.key
}
@ -1718,7 +1717,7 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
/// Gets a reference to the key in the entry.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
self.handle.reborrow().into_kv().0
}

View File

@ -27,7 +27,6 @@
test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]
#![cfg_attr(test, allow(deprecated))] // rand
#![cfg_attr(not(test), feature(slice_binary_search_by_key))] // impl [T]
#![cfg_attr(not(stage0), deny(warnings))]
#![feature(alloc)]

View File

@ -759,7 +759,6 @@ impl<T> [T] {
/// fourth could match any position in `[1,4]`.
///
/// ```rust
/// #![feature(slice_binary_search_by_key)]
/// let s = [(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
/// (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
/// (1, 21), (2, 34), (4, 55)];
@ -770,7 +769,7 @@ impl<T> [T] {
/// let r = s.binary_search_by_key(&1, |&(a,b)| b);
/// assert!(match r { Ok(1...4) => true, _ => false, });
/// ```
#[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "33018")]
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
#[inline]
pub fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
where F: FnMut(&T) -> B,

View File

@ -22,8 +22,6 @@
#![feature(enumset)]
#![feature(iter_arith)]
#![feature(linked_list_contains)]
#![feature(map_entry_keys)]
#![feature(map_values_mut)]
#![feature(pattern)]
#![feature(rand)]
#![feature(step_by)]

View File

@ -15,11 +15,9 @@
#![allow(non_snake_case)]
#![stable(feature = "core_char", since = "1.2.0")]
use iter::Iterator;
use prelude::v1::*;
use mem::transmute;
use option::Option::{None, Some};
use option::Option;
use slice::SliceExt;
// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;

View File

@ -1125,6 +1125,7 @@ impl<I: Iterator> Peekable<I> {
/// ```
#[unstable(feature = "peekable_is_empty", issue = "32111")]
#[inline]
#[rustc_deprecated(since = "1.10.0", reason = "replaced by .peek().is_none()")]
pub fn is_empty(&mut self) -> bool {
self.peek().is_none()
}

View File

@ -106,6 +106,10 @@ pub trait SliceExt {
#[stable(feature = "core", since = "1.6.0")]
fn binary_search_by<F>(&self, f: F) -> Result<usize, usize>
where F: FnMut(&Self::Item) -> Ordering;
#[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
where F: FnMut(&Self::Item) -> B,
B: Ord;
#[stable(feature = "core", since = "1.6.0")]
fn len(&self) -> usize;
#[stable(feature = "core", since = "1.6.0")]
@ -157,11 +161,6 @@ pub trait SliceExt {
fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
#[stable(feature = "copy_from_slice", since = "1.9.0")]
fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
#[unstable(feature = "slice_binary_search_by_key", reason = "recently added", issue = "33018")]
fn binary_search_by_key<B, F>(&self, b: &B, f: F) -> Result<usize, usize>
where F: FnMut(&Self::Item) -> B,
B: Ord;
}
// Use macros to be generic over const/mut

View File

@ -299,7 +299,6 @@ impl AtomicBool {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// let some_bool = AtomicBool::new(true);
@ -318,7 +317,7 @@ impl AtomicBool {
/// assert_eq!(some_bool.load(Ordering::Relaxed), false);
/// ```
#[inline]
#[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
pub fn compare_exchange(&self,
current: bool,
new: bool,
@ -347,7 +346,6 @@ impl AtomicBool {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// let val = AtomicBool::new(false);
@ -362,7 +360,7 @@ impl AtomicBool {
/// }
/// ```
#[inline]
#[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
pub fn compare_exchange_weak(&self,
current: bool,
new: bool,
@ -645,7 +643,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
@ -658,7 +655,7 @@ impl<T> AtomicPtr<T> {
/// Ordering::SeqCst, Ordering::Relaxed);
/// ```
#[inline]
#[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
pub fn compare_exchange(&self,
current: *mut T,
new: *mut T,
@ -693,7 +690,6 @@ impl<T> AtomicPtr<T> {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let some_ptr = AtomicPtr::new(&mut 5);
@ -708,7 +704,7 @@ impl<T> AtomicPtr<T> {
/// }
/// ```
#[inline]
#[unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767")]
#[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
pub fn compare_exchange_weak(&self,
current: *mut T,
new: *mut T,
@ -901,7 +897,6 @@ macro_rules! atomic_int {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicIsize, Ordering};
///
/// let some_isize = AtomicIsize::new(5);
@ -945,7 +940,6 @@ macro_rules! atomic_int {
/// # Examples
///
/// ```
/// # #![feature(extended_compare_and_swap)]
/// use std::sync::atomic::{AtomicIsize, Ordering};
///
/// let val = AtomicIsize::new(4);
@ -1115,14 +1109,14 @@ atomic_int! {
#[cfg(any(stage0, target_has_atomic = "ptr"))]
atomic_int!{
stable(feature = "rust1", since = "1.0.0"),
unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
isize AtomicIsize ATOMIC_ISIZE_INIT
}
#[cfg(any(stage0, target_has_atomic = "ptr"))]
atomic_int!{
stable(feature = "rust1", since = "1.0.0"),
unstable(feature = "extended_compare_and_swap", reason = "recently added", issue = "31767"),
stable(feature = "extended_compare_and_swap", since = "1.10.0"),
stable(feature = "atomic_debug", since = "1.3.0"),
usize AtomicUsize ATOMIC_USIZE_INIT
}

View File

@ -902,15 +902,6 @@ fn test_range_step() {
assert_eq!((isize::MIN..isize::MAX).step_by(1).size_hint(), (usize::MAX, Some(usize::MAX)));
}
#[test]
fn test_peekable_is_empty() {
let a = [1];
let mut it = a.iter().peekable();
assert!( !it.is_empty() );
it.next();
assert!( it.is_empty() );
}
#[test]
fn test_repeat() {
let mut it = repeat(42);

View File

@ -24,7 +24,6 @@
#![feature(iter_arith)]
#![feature(libc)]
#![feature(nonzero)]
#![feature(peekable_is_empty)]
#![feature(rand)]
#![feature(raw)]
#![feature(slice_patterns)]

View File

@ -170,10 +170,7 @@
#![deny(missing_docs)]
#![cfg_attr(not(stage0), deny(warnings))]
#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(staged_api)]
#![feature(static_mutex)]
use std::cell::RefCell;
use std::fmt;
@ -181,9 +178,8 @@ use std::io::{self, Stderr};
use std::io::prelude::*;
use std::mem;
use std::env;
use std::ptr;
use std::slice;
use std::sync::{Once, StaticMutex};
use std::sync::{Once, Mutex, ONCE_INIT};
use directive::LOG_LEVEL_NAMES;
@ -199,18 +195,13 @@ pub const MAX_LOG_LEVEL: u32 = 255;
/// The default logging level of a crate if no other is specified.
const DEFAULT_LOG_LEVEL: u32 = 1;
static LOCK: StaticMutex = StaticMutex::new();
static mut LOCK: *mut Mutex<(Vec<directive::LogDirective>, Option<String>)> = 0 as *mut _;
/// An unsafe constant that is the maximum logging level of any module
/// specified. This is the first line of defense to determining whether a
/// logging statement should be run.
static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
static mut DIRECTIVES: *mut Vec<directive::LogDirective> = ptr::null_mut();
/// Optional filter.
static mut FILTER: *mut String = ptr::null_mut();
/// Debug log level
pub const DEBUG: u32 = 4;
/// Info log level
@ -287,14 +278,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
// Test the literal string from args against the current filter, if there
// is one.
unsafe {
let _g = LOCK.lock();
match FILTER as usize {
0 => {}
n => {
let filter = mem::transmute::<_, &String>(n);
if !args.to_string().contains(filter) {
return;
}
let filter = (*LOCK).lock().unwrap();
if let Some(ref filter) = filter.1 {
if !args.to_string().contains(filter) {
return;
}
}
}
@ -302,10 +289,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
// Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| s.borrow_mut().take())
.unwrap_or_else(|| {
box DefaultLogger { handle: io::stderr() }
});
let logger = LOCAL_LOGGER.with(|s| s.borrow_mut().take());
let mut logger = logger.unwrap_or_else(|| {
Box::new(DefaultLogger { handle: io::stderr() })
});
logger.log(&LogRecord {
level: LogLevel(level),
args: args,
@ -363,7 +350,7 @@ pub struct LogLocation {
/// module's log statement should be emitted or not.
#[doc(hidden)]
pub fn mod_enabled(level: u32, module: &str) -> bool {
static INIT: Once = Once::new();
static INIT: Once = ONCE_INIT;
INIT.call_once(init);
// It's possible for many threads are in this function, only one of them
@ -378,10 +365,9 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
// This assertion should never get tripped unless we're in an at_exit
// handler after logging has been torn down and a logging attempt was made.
let _g = LOCK.lock();
unsafe {
assert!(DIRECTIVES as usize != 0);
enabled(level, module, (*DIRECTIVES).iter())
let directives = (*LOCK).lock().unwrap();
enabled(level, module, directives.0.iter())
}
}
@ -422,14 +408,8 @@ fn init() {
unsafe {
LOG_LEVEL = max_level;
assert!(FILTER.is_null());
match filter {
Some(f) => FILTER = Box::into_raw(box f),
None => {}
}
assert!(DIRECTIVES.is_null());
DIRECTIVES = Box::into_raw(box directives);
assert!(LOCK.is_null());
LOCK = Box::into_raw(Box::new(Mutex::new((directives, filter))));
}
}

View File

@ -189,12 +189,16 @@ mod dl {
pub fn check_for_errors_in<T, F>(f: F) -> Result<T, String> where
F: FnOnce() -> T,
{
use std::sync::StaticMutex;
static LOCK: StaticMutex = StaticMutex::new();
use std::sync::{Mutex, Once, ONCE_INIT};
static INIT: Once = ONCE_INIT;
static mut LOCK: *mut Mutex<()> = 0 as *mut _;
unsafe {
INIT.call_once(|| {
LOCK = Box::into_raw(Box::new(Mutex::new(())));
});
// dlerror isn't thread safe, so we need to lock around this entire
// sequence
let _guard = LOCK.lock();
let _guard = (*LOCK).lock();
let _old_error = libc::dlerror();
let result = f();

View File

@ -38,7 +38,6 @@
#![feature(staged_api)]
#![feature(step_by)]
#![feature(question_mark)]
#![cfg_attr(unix, feature(static_mutex))]
#![cfg_attr(test, feature(test, rand))]
extern crate syntax;

View File

@ -864,7 +864,6 @@ impl<K, V, S> HashMap<K, V, S>
/// # Examples
///
/// ```
/// # #![feature(map_values_mut)]
/// use std::collections::HashMap;
///
/// let mut map = HashMap::new();
@ -881,8 +880,8 @@ impl<K, V, S> HashMap<K, V, S>
/// print!("{}", val);
/// }
/// ```
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
pub fn values_mut<'a>(&'a mut self) -> ValuesMut<K, V> {
#[stable(feature = "map_values_mut", since = "1.10.0")]
pub fn values_mut(&mut self) -> ValuesMut<K, V> {
ValuesMut { inner: self.iter_mut() }
}
@ -1288,7 +1287,7 @@ pub struct Drain<'a, K: 'a, V: 'a> {
}
/// Mutable HashMap values iterator.
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
pub struct ValuesMut<'a, K: 'a, V: 'a> {
inner: IterMut<'a, K, V>
}
@ -1491,14 +1490,14 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;
#[inline] fn next(&mut self) -> Option<(&'a mut V)> { self.inner.next().map(|(_, v)| v) }
#[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
#[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
#[stable(feature = "map_values_mut", since = "1.10.0")]
impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
#[inline] fn len(&self) -> usize { self.inner.len() }
}
@ -1537,7 +1536,7 @@ impl<'a, K, V> Entry<'a, K, V> {
}
/// Returns a reference to this entry's key.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
match *self {
Occupied(ref entry) => entry.key(),
@ -1548,7 +1547,7 @@ impl<'a, K, V> Entry<'a, K, V> {
impl<'a, K, V> OccupiedEntry<'a, K, V> {
/// Gets a reference to the key in the entry.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
self.elem.read().0
}
@ -1596,7 +1595,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
/// Gets a reference to the key that would be used when inserting a value
/// through the VacantEntry.
#[unstable(feature = "map_entry_keys", issue = "32281")]
#[stable(feature = "map_entry_keys", since = "1.10.0")]
pub fn key(&self) -> &K {
&self.key
}

View File

@ -159,6 +159,12 @@ pub struct CStr {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct NulError(usize, Vec<u8>);
/// An error returned from `CStr::from_bytes_with_nul` to indicate that a nul
/// byte was found too early in the slice provided or one wasn't found at all.
#[derive(Clone, PartialEq, Debug)]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub struct FromBytesWithNulError { _a: () }
/// An error returned from `CString::into_string` to indicate that a UTF-8 error
/// was encountered during the conversion.
#[derive(Clone, PartialEq, Debug)]
@ -461,20 +467,18 @@ impl CStr {
/// # Examples
///
/// ```
/// # #![feature(cstr_from_bytes)]
/// use std::ffi::CStr;
///
/// # fn main() {
/// let cstr = CStr::from_bytes_with_nul(b"hello\0");
/// assert!(cstr.is_some());
/// # }
/// assert!(cstr.is_ok());
/// ```
#[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
pub fn from_bytes_with_nul(bytes: &[u8]) -> Option<&CStr> {
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub fn from_bytes_with_nul(bytes: &[u8])
-> Result<&CStr, FromBytesWithNulError> {
if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
None
Err(FromBytesWithNulError { _a: () })
} else {
Some(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
}
}
@ -487,18 +491,15 @@ impl CStr {
/// # Examples
///
/// ```
/// # #![feature(cstr_from_bytes)]
/// use std::ffi::{CStr, CString};
///
/// # fn main() {
/// unsafe {
/// let cstring = CString::new("hello").unwrap();
/// let cstr = CStr::from_bytes_with_nul_unchecked(cstring.to_bytes_with_nul());
/// assert_eq!(cstr, &*cstring);
/// }
/// # }
/// ```
#[unstable(feature = "cstr_from_bytes", reason = "recently added", issue = "31190")]
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
mem::transmute(bytes)
}
@ -742,12 +743,14 @@ mod tests {
fn from_bytes_with_nul() {
let data = b"123\0";
let cstr = CStr::from_bytes_with_nul(data);
assert_eq!(cstr.map(CStr::to_bytes), Some(&b"123"[..]));
assert_eq!(cstr.map(CStr::to_bytes_with_nul), Some(&b"123\0"[..]));
assert_eq!(cstr.map(CStr::to_bytes), Ok(&b"123"[..]));
let cstr = CStr::from_bytes_with_nul(data);
assert_eq!(cstr.map(CStr::to_bytes_with_nul), Ok(&b"123\0"[..]));
unsafe {
let cstr = CStr::from_bytes_with_nul(data);
let cstr_unchecked = CStr::from_bytes_with_nul_unchecked(data);
assert_eq!(cstr, Some(cstr_unchecked));
assert_eq!(cstr, Ok(cstr_unchecked));
}
}
@ -755,13 +758,13 @@ mod tests {
fn from_bytes_with_nul_unterminated() {
let data = b"123";
let cstr = CStr::from_bytes_with_nul(data);
assert!(cstr.is_none());
assert!(cstr.is_err());
}
#[test]
fn from_bytes_with_nul_interior() {
let data = b"1\023\0";
let cstr = CStr::from_bytes_with_nul(data);
assert!(cstr.is_none());
assert!(cstr.is_err());
}
}

View File

@ -14,6 +14,8 @@
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::c_str::{CString, CStr, NulError, IntoStringError};
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
pub use self::c_str::{FromBytesWithNulError};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::os_str::{OsString, OsStr};

View File

@ -657,7 +657,7 @@ impl Metadata {
///
/// This field may not be available on all platforms, and will return an
/// `Err` on platforms where it is not available.
#[unstable(feature = "fs_time", issue = "31399")]
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn modified(&self) -> io::Result<SystemTime> {
self.0.modified().map(FromInner::from_inner)
}
@ -675,7 +675,7 @@ impl Metadata {
///
/// This field may not be available on all platforms, and will return an
/// `Err` on platforms where it is not available.
#[unstable(feature = "fs_time", issue = "31399")]
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn accessed(&self) -> io::Result<SystemTime> {
self.0.accessed().map(FromInner::from_inner)
}
@ -689,7 +689,7 @@ impl Metadata {
///
/// This field may not be available on all platforms, and will return an
/// `Err` on platforms where it is not available.
#[unstable(feature = "fs_time", issue = "31399")]
#[stable(feature = "fs_time", since = "1.10.0")]
pub fn created(&self) -> io::Result<SystemTime> {
self.0.created().map(FromInner::from_inner)
}

View File

@ -12,11 +12,12 @@ use prelude::v1::*;
use cell::Cell;
use ptr;
use sync::{StaticMutex, Arc};
use sync::Arc;
use sys_common;
use sys_common::mutex::Mutex;
pub struct Lazy<T> {
lock: StaticMutex,
lock: Mutex,
ptr: Cell<*mut Arc<T>>,
init: fn() -> Arc<T>,
}
@ -26,23 +27,25 @@ unsafe impl<T> Sync for Lazy<T> {}
impl<T: Send + Sync + 'static> Lazy<T> {
pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
Lazy {
lock: StaticMutex::new(),
lock: Mutex::new(),
ptr: Cell::new(ptr::null_mut()),
init: init
}
}
pub fn get(&'static self) -> Option<Arc<T>> {
let _g = self.lock.lock();
let ptr = self.ptr.get();
unsafe {
if ptr.is_null() {
self.lock.lock();
let ptr = self.ptr.get();
let ret = if ptr.is_null() {
Some(self.init())
} else if ptr as usize == 1 {
None
} else {
Some((*ptr).clone())
}
};
self.lock.unlock();
return ret
}
}
@ -52,10 +55,10 @@ impl<T: Send + Sync + 'static> Lazy<T> {
// the at exit handler). Otherwise we just return the freshly allocated
// `Arc`.
let registered = sys_common::at_exit(move || {
let g = self.lock.lock();
self.lock.lock();
let ptr = self.ptr.get();
self.ptr.set(1 as *mut _);
drop(g);
self.lock.unlock();
drop(Box::from_raw(ptr))
});
let ret = (self.init)();

View File

@ -22,7 +22,7 @@ use rc::Rc;
use sync::{Arc, Mutex, RwLock};
use thread::Result;
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub use panicking::{take_hook, set_hook, PanicInfo, Location};
///

View File

@ -27,7 +27,7 @@ use fmt;
use intrinsics;
use mem;
use raw;
use sync::StaticRwLock;
use sys_common::rwlock::RWLock;
use sync::atomic::{AtomicBool, Ordering};
use sys::stdio::Stderr;
use sys_common::backtrace;
@ -69,7 +69,7 @@ enum Hook {
Custom(*mut (Fn(&PanicInfo) + 'static + Sync + Send)),
}
static HOOK_LOCK: StaticRwLock = StaticRwLock::new();
static HOOK_LOCK: RWLock = RWLock::new();
static mut HOOK: Hook = Hook::Default;
static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
@ -90,17 +90,17 @@ static FIRST_PANIC: AtomicBool = AtomicBool::new(true);
/// # Panics
///
/// Panics if called from a panicking thread.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
if thread::panicking() {
panic!("cannot modify the panic hook from a panicking thread");
}
unsafe {
let lock = HOOK_LOCK.write();
HOOK_LOCK.write();
let old_hook = HOOK;
HOOK = Hook::Custom(Box::into_raw(hook));
drop(lock);
HOOK_LOCK.write_unlock();
if let Hook::Custom(ptr) = old_hook {
Box::from_raw(ptr);
@ -115,17 +115,17 @@ pub fn set_hook(hook: Box<Fn(&PanicInfo) + 'static + Sync + Send>) {
/// # Panics
///
/// Panics if called from a panicking thread.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
if thread::panicking() {
panic!("cannot modify the panic hook from a panicking thread");
}
unsafe {
let lock = HOOK_LOCK.write();
HOOK_LOCK.write();
let hook = HOOK;
HOOK = Hook::Default;
drop(lock);
HOOK_LOCK.write_unlock();
match hook {
Hook::Default => Box::new(default_hook),
@ -135,7 +135,7 @@ pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
}
/// A struct providing information about a panic.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct PanicInfo<'a> {
payload: &'a (Any + Send),
location: Location<'a>,
@ -145,7 +145,7 @@ impl<'a> PanicInfo<'a> {
/// Returns the payload associated with the panic.
///
/// This will commonly, but not always, be a `&'static str` or `String`.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn payload(&self) -> &(Any + Send) {
self.payload
}
@ -155,14 +155,14 @@ impl<'a> PanicInfo<'a> {
///
/// This method will currently always return `Some`, but this may change
/// in future versions.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn location(&self) -> Option<&Location> {
Some(&self.location)
}
}
/// A struct containing information about the location of a panic.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
file: &'a str,
line: u32,
@ -170,13 +170,13 @@ pub struct Location<'a> {
impl<'a> Location<'a> {
/// Returns the name of the source file from which the panic originated.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn file(&self) -> &str {
self.file
}
/// Returns the line number from which the panic originated.
#[unstable(feature = "panic_handler", issue = "30449")]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub fn line(&self) -> u32 {
self.line
}
@ -365,11 +365,12 @@ fn rust_panic_with_hook(msg: Box<Any + Send>,
line: line,
},
};
let _lock = HOOK_LOCK.read();
HOOK_LOCK.read();
match HOOK {
Hook::Default => default_hook(&info),
Hook::Custom(ptr) => (*ptr)(&info),
}
HOOK_LOCK.read_unlock();
}
if panics > 0 {

View File

@ -72,6 +72,7 @@ impl WaitTimeoutResult {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct Condvar { inner: Box<StaticCondvar> }
/// Statically allocated condition variables.
@ -91,6 +92,11 @@ pub struct Condvar { inner: Box<StaticCondvar> }
#[unstable(feature = "static_condvar",
reason = "may be merged with Condvar in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Condvar::new` in a static should \
suffice")]
pub struct StaticCondvar {
inner: sys::Condvar,
mutex: AtomicUsize,
@ -100,8 +106,15 @@ pub struct StaticCondvar {
#[unstable(feature = "static_condvar",
reason = "may be merged with Condvar in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Condvar::new` in a static should \
suffice")]
#[allow(deprecated)]
pub const CONDVAR_INIT: StaticCondvar = StaticCondvar::new();
#[allow(deprecated)]
impl Condvar {
/// Creates a new condition variable which is ready to be waited on and
/// notified.
@ -228,12 +241,22 @@ impl Default for Condvar {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl Drop for Condvar {
fn drop(&mut self) {
unsafe { self.inner.inner.destroy() }
}
}
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Condvar::new` in a static should \
suffice")]
#[unstable(feature = "static_condvar",
reason = "may be merged with Condvar in the future",
issue = "27717")]
#[allow(deprecated)]
impl StaticCondvar {
/// Creates a new condition variable
#[unstable(feature = "static_condvar",
@ -392,6 +415,7 @@ impl StaticCondvar {
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use prelude::v1::*;

View File

@ -25,10 +25,13 @@ pub use core::sync::atomic;
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::barrier::{Barrier, BarrierWaitResult};
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::condvar::{Condvar, StaticCondvar, WaitTimeoutResult, CONDVAR_INIT};
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::mutex::MUTEX_INIT;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::mutex::{Mutex, MutexGuard, StaticMutex};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::once::{Once, OnceState, ONCE_INIT};
@ -37,6 +40,7 @@ pub use sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResul
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::rwlock::{RwLockReadGuard, RwLockWriteGuard};
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub use self::rwlock::{RwLock, StaticRwLock, RW_LOCK_INIT};
pub mod mpsc;

View File

@ -113,6 +113,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
/// *guard += 1;
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct Mutex<T: ?Sized> {
// 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
@ -156,6 +157,11 @@ unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { }
#[unstable(feature = "static_mutex",
reason = "may be merged with Mutex in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Mutex::new` in a static should \
suffice")]
pub struct StaticMutex {
lock: sys::Mutex,
poison: poison::Flag,
@ -168,6 +174,7 @@ pub struct StaticMutex {
/// `Deref` and `DerefMut` implementations
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
// funny underscores due to how Deref/DerefMut currently work (they
// disregard field privacy).
@ -184,8 +191,15 @@ impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {}
#[unstable(feature = "static_mutex",
reason = "may be merged with Mutex in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Mutex::new` in a static should \
suffice")]
#[allow(deprecated)]
pub const MUTEX_INIT: StaticMutex = StaticMutex::new();
#[allow(deprecated)]
impl<T> Mutex<T> {
/// Creates a new mutex in an unlocked state ready for use.
#[stable(feature = "rust1", since = "1.0.0")]
@ -197,6 +211,7 @@ impl<T> Mutex<T> {
}
}
#[allow(deprecated)]
impl<T: ?Sized> Mutex<T> {
/// Acquires a mutex, blocking the current thread until it is able to do so.
///
@ -307,6 +322,7 @@ impl<T: ?Sized> Mutex<T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<T: ?Sized> Drop for Mutex<T> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
@ -346,6 +362,12 @@ static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
#[unstable(feature = "static_mutex",
reason = "may be merged with Mutex in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `Mutex::new` in a static should \
suffice")]
#[allow(deprecated)]
impl StaticMutex {
/// Creates a new mutex in an unlocked state ready for use.
pub const fn new() -> StaticMutex {
@ -391,8 +413,8 @@ impl StaticMutex {
}
}
#[allow(deprecated)]
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
unsafe fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>)
-> LockResult<MutexGuard<'mutex, T>> {
poison::map_result(lock.poison.borrow(), |guard| {
@ -418,6 +440,7 @@ impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
#[inline]
fn drop(&mut self) {
@ -428,15 +451,18 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
}
}
#[allow(deprecated)]
pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
&guard.__lock.lock
}
#[allow(deprecated)]
pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag {
&guard.__lock.poison
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use prelude::v1::*;

View File

@ -66,6 +66,7 @@ use sys_common::rwlock as sys;
/// } // write lock is dropped here
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct RwLock<T: ?Sized> {
inner: Box<StaticRwLock>,
data: UnsafeCell<T>,
@ -104,6 +105,11 @@ unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {}
#[unstable(feature = "static_rwlock",
reason = "may be merged with RwLock in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `RwLock::new` in a static should \
suffice")]
pub struct StaticRwLock {
lock: sys::RWLock,
poison: poison::Flag,
@ -113,12 +119,19 @@ pub struct StaticRwLock {
#[unstable(feature = "static_rwlock",
reason = "may be merged with RwLock in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `RwLock::new` in a static should \
suffice")]
#[allow(deprecated)]
pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock::new();
/// RAII structure used to release the shared read access of a lock when
/// dropped.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
__lock: &'a StaticRwLock,
__data: &'a T,
@ -131,6 +144,7 @@ impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {}
/// dropped.
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
__lock: &'a StaticRwLock,
__data: &'a mut T,
@ -140,6 +154,7 @@ pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {}
#[allow(deprecated)]
impl<T> RwLock<T> {
/// Creates a new instance of an `RwLock<T>` which is unlocked.
///
@ -156,6 +171,7 @@ impl<T> RwLock<T> {
}
}
#[allow(deprecated)]
impl<T: ?Sized> RwLock<T> {
/// Locks this rwlock with shared read access, blocking the current thread
/// until it can be acquired.
@ -325,6 +341,7 @@ impl<T: ?Sized> RwLock<T> {
}
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl<T: ?Sized> Drop for RwLock<T> {
#[unsafe_destructor_blind_to_params]
fn drop(&mut self) {
@ -360,6 +377,12 @@ static DUMMY: Dummy = Dummy(UnsafeCell::new(()));
#[unstable(feature = "static_rwlock",
reason = "may be merged with RwLock in the future",
issue = "27717")]
#[rustc_deprecated(since = "1.10.0",
reason = "the lazy-static crate suffices for static sync \
primitives and eventually this type shouldn't \
be necessary as `RwLock::new` in a static should \
suffice")]
#[allow(deprecated)]
impl StaticRwLock {
/// Creates a new rwlock.
pub const fn new() -> StaticRwLock {
@ -434,6 +457,7 @@ impl StaticRwLock {
}
}
#[allow(deprecated)]
impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
-> LockResult<RwLockReadGuard<'rwlock, T>> {
@ -482,6 +506,7 @@ impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> {
}
}
#[allow(deprecated)]
impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
unsafe fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>)
-> LockResult<RwLockWriteGuard<'rwlock, T>> {
@ -562,10 +587,12 @@ impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> {
fn deref_mut(&mut self) -> &mut T { self.__data
fn deref_mut(&mut self) -> &mut T {
self.__data
}
}
#[allow(deprecated)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
fn drop(&mut self) {
@ -573,6 +600,7 @@ impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> {
}
}
#[allow(deprecated)]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
fn drop(&mut self) {
@ -582,6 +610,7 @@ impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> {
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
#![allow(deprecated)] // rand

View File

@ -48,32 +48,36 @@ mod imp {
use mem;
use ffi::CStr;
use sync::StaticMutex;
use sys_common::mutex::Mutex;
static mut GLOBAL_ARGS_PTR: usize = 0;
static LOCK: StaticMutex = StaticMutex::new();
static LOCK: Mutex = Mutex::new();
pub unsafe fn init(argc: isize, argv: *const *const u8) {
let args = (0..argc).map(|i| {
CStr::from_ptr(*argv.offset(i) as *const c_char).to_bytes().to_vec()
}).collect();
let _guard = LOCK.lock();
LOCK.lock();
let ptr = get_global_ptr();
assert!((*ptr).is_none());
(*ptr) = Some(box args);
LOCK.unlock();
}
pub unsafe fn cleanup() {
let _guard = LOCK.lock();
LOCK.lock();
*get_global_ptr() = None;
LOCK.unlock();
}
pub fn clone() -> Option<Vec<Vec<u8>>> {
let _guard = LOCK.lock();
unsafe {
LOCK.lock();
let ptr = get_global_ptr();
(*ptr).as_ref().map(|s| (**s).clone())
let ret = (*ptr).as_ref().map(|s| (**s).clone());
LOCK.unlock();
return ret
}
}

View File

@ -18,12 +18,11 @@
/// simple to use it should be used only on iOS devices as the only viable
/// option.
use io;
use io::prelude::*;
use io;
use libc;
use mem;
use result::Result::Ok;
use sync::StaticMutex;
use sys::mutex::Mutex;
use super::super::printing::print;
@ -37,18 +36,21 @@ pub fn write(w: &mut Write) -> io::Result<()> {
// while it doesn't requires lock for work as everything is
// local, it still displays much nicer backtraces when a
// couple of threads panic simultaneously
static LOCK: StaticMutex = StaticMutex::new();
let _g = LOCK.lock();
static LOCK: Mutex = Mutex::new();
unsafe {
LOCK.lock();
writeln!(w, "stack backtrace:")?;
// 100 lines should be enough
const SIZE: usize = 100;
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 usize};
writeln!(w, "stack backtrace:")?;
// 100 lines should be enough
const SIZE: usize = 100;
let mut buf: [*mut libc::c_void; SIZE] = mem::zeroed();
let cnt = backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as usize;
// skipping the first one as it is write itself
for i in 1..cnt {
print(w, i as isize, buf[i], buf[i])?
// skipping the first one as it is write itself
for i in 1..cnt {
print(w, i as isize, buf[i], buf[i])?
}
LOCK.unlock();
}
Ok(())
}

View File

@ -12,7 +12,7 @@ use io;
use io::prelude::*;
use libc;
use mem;
use sync::StaticMutex;
use sys_common::mutex::Mutex;
use super::super::printing::print;
use unwind as uw;
@ -31,24 +31,28 @@ pub fn write(w: &mut Write) -> io::Result<()> {
// is semi-reasonable in terms of printing anyway, and we know that all
// I/O done here is blocking I/O, not green I/O, so we don't have to
// worry about this being a native vs green mutex.
static LOCK: StaticMutex = StaticMutex::new();
let _g = LOCK.lock();
static LOCK: Mutex = Mutex::new();
unsafe {
LOCK.lock();
writeln!(w, "stack backtrace:")?;
writeln!(w, "stack backtrace:")?;
let mut cx = Context { writer: w, last_error: None, idx: 0 };
return match unsafe {
uw::_Unwind_Backtrace(trace_fn,
&mut cx as *mut Context as *mut libc::c_void)
} {
uw::_URC_NO_REASON => {
match cx.last_error {
Some(err) => Err(err),
None => Ok(())
let mut cx = Context { writer: w, last_error: None, idx: 0 };
let ret = match {
uw::_Unwind_Backtrace(trace_fn,
&mut cx as *mut Context as *mut libc::c_void)
} {
uw::_URC_NO_REASON => {
match cx.last_error {
Some(err) => Err(err),
None => Ok(())
}
}
}
_ => Ok(()),
};
_ => Ok(()),
};
LOCK.unlock();
return ret
}
extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {

View File

@ -88,9 +88,7 @@ pub trait OpenOptionsExt {
/// }
/// let file = options.open("foo.txt");
/// ```
#[unstable(feature = "expand_open_options",
reason = "recently added",
issue = "30014")]
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn custom_flags(&mut self, flags: i32) -> &mut Self;
}

View File

@ -7,7 +7,8 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![unstable(feature = "unix_socket", reason = "newly added", issue = "32312")]
#![stable(feature = "unix_socket", since = "1.10.0")]
//! Unix-specific networking functionality
@ -75,6 +76,7 @@ enum AddressKind<'a> {
/// An address associated with a Unix socket.
#[derive(Clone)]
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct SocketAddr {
addr: libc::sockaddr_un,
len: libc::socklen_t,
@ -109,6 +111,7 @@ impl SocketAddr {
}
/// Returns true iff the address is unnamed.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn is_unnamed(&self) -> bool {
if let AddressKind::Unnamed = self.address() {
true
@ -118,6 +121,7 @@ impl SocketAddr {
}
/// Returns the contents of this address if it is a `pathname` address.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn as_pathname(&self) -> Option<&Path> {
if let AddressKind::Pathname(path) = self.address() {
Some(path)
@ -141,6 +145,7 @@ impl SocketAddr {
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.address() {
@ -168,8 +173,6 @@ impl<'a> fmt::Display for AsciiEscaped<'a> {
/// # Examples
///
/// ```rust,no_run
/// #![feature(unix_socket)]
///
/// use std::os::unix::net::UnixStream;
/// use std::io::prelude::*;
///
@ -179,8 +182,10 @@ impl<'a> fmt::Display for AsciiEscaped<'a> {
/// stream.read_to_string(&mut response).unwrap();
/// println!("{}", response);
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixStream(Socket);
#[stable(feature = "unix_socket", since = "1.10.0")]
impl fmt::Debug for UnixStream {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut builder = fmt.debug_struct("UnixStream");
@ -197,6 +202,7 @@ impl fmt::Debug for UnixStream {
impl UnixStream {
/// Connects to the socket named by `path`.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
fn inner(path: &Path) -> io::Result<UnixStream> {
unsafe {
@ -213,6 +219,7 @@ impl UnixStream {
/// Creates an unnamed pair of connected sockets.
///
/// Returns two `UnixStream`s which are connected to each other.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
Ok((UnixStream(i1), UnixStream(i2)))
@ -224,16 +231,19 @@ impl UnixStream {
/// object references. Both handles will read and write the same stream of
/// data, and options set on one stream will be propogated to the other
/// stream.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixStream> {
self.0.duplicate().map(UnixStream)
}
/// Returns the socket address of the local half of this connection.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
}
/// Returns the socket address of the remote half of this connection.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
}
@ -243,6 +253,7 @@ impl UnixStream {
/// If the provided value is `None`, then `read` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// method.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
}
@ -252,26 +263,31 @@ impl UnixStream {
/// If the provided value is `None`, then `write` calls will block
/// indefinitely. It is an error to pass the zero `Duration` to this
/// method.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
}
/// Returns the read timeout of this socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.0.timeout(libc::SO_RCVTIMEO)
}
/// Returns the write timeout of this socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.0.timeout(libc::SO_SNDTIMEO)
}
/// Moves the socket into or out of nonblocking mode.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
/// Returns the value of the `SO_ERROR` option.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
}
@ -281,11 +297,13 @@ impl UnixStream {
/// This function will cause all pending and future I/O calls on the
/// specified portions to immediately return with an appropriate value
/// (see the documentation of `Shutdown`).
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.0.shutdown(how)
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl io::Read for UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
io::Read::read(&mut &*self, buf)
@ -296,6 +314,7 @@ impl io::Read for UnixStream {
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl<'a> io::Read for &'a UnixStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
@ -306,6 +325,7 @@ impl<'a> io::Read for &'a UnixStream {
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl io::Write for UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
io::Write::write(&mut &*self, buf)
@ -316,6 +336,7 @@ impl io::Write for UnixStream {
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl<'a> io::Write for &'a UnixStream {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
@ -326,18 +347,21 @@ impl<'a> io::Write for &'a UnixStream {
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl AsRawFd for UnixStream {
fn as_raw_fd(&self) -> RawFd {
*self.0.as_inner()
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl FromRawFd for UnixStream {
unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
UnixStream(Socket::from_inner(fd))
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl IntoRawFd for UnixStream {
fn into_raw_fd(self) -> RawFd {
self.0.into_inner()
@ -349,8 +373,6 @@ impl IntoRawFd for UnixStream {
/// # Examples
///
/// ```rust,no_run
/// #![feature(unix_socket)]
///
/// use std::thread;
/// use std::os::unix::net::{UnixStream, UnixListener};
///
@ -377,8 +399,10 @@ impl IntoRawFd for UnixStream {
/// // close the listener socket
/// drop(listener);
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixListener(Socket);
#[stable(feature = "unix_socket", since = "1.10.0")]
impl fmt::Debug for UnixListener {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut builder = fmt.debug_struct("UnixListener");
@ -392,6 +416,7 @@ impl fmt::Debug for UnixListener {
impl UnixListener {
/// Creates a new `UnixListener` bound to the specified socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
fn inner(path: &Path) -> io::Result<UnixListener> {
unsafe {
@ -412,6 +437,7 @@ impl UnixListener {
/// This function will block the calling thread until a new Unix connection
/// is established. When established, the corersponding `UnixStream` and
/// the remote peer's address will be returned.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
let mut len = mem::size_of_val(&storage) as libc::socklen_t;
@ -425,21 +451,25 @@ impl UnixListener {
/// The returned `UnixListener` is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixListener> {
self.0.duplicate().map(UnixListener)
}
/// Returns the local socket address of this listener.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
}
/// Moves the socket into or out of nonblocking mode.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
/// Returns the value of the `SO_ERROR` option.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
}
@ -448,29 +478,34 @@ impl UnixListener {
///
/// The iterator will never return `None` and will also not yield the
/// peer's `SocketAddr` structure.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn incoming<'a>(&'a self) -> Incoming<'a> {
Incoming { listener: self }
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl AsRawFd for UnixListener {
fn as_raw_fd(&self) -> RawFd {
*self.0.as_inner()
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl FromRawFd for UnixListener {
unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
UnixListener(Socket::from_inner(fd))
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl IntoRawFd for UnixListener {
fn into_raw_fd(self) -> RawFd {
self.0.into_inner()
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl<'a> IntoIterator for &'a UnixListener {
type Item = io::Result<UnixStream>;
type IntoIter = Incoming<'a>;
@ -484,10 +519,12 @@ impl<'a> IntoIterator for &'a UnixListener {
///
/// It will never return `None`.
#[derive(Debug)]
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct Incoming<'a> {
listener: &'a UnixListener,
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl<'a> Iterator for Incoming<'a> {
type Item = io::Result<UnixStream>;
@ -505,8 +542,6 @@ impl<'a> Iterator for Incoming<'a> {
/// # Examples
///
/// ```rust,no_run
/// #![feature(unix_socket)]
///
/// use std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
@ -515,8 +550,10 @@ impl<'a> Iterator for Incoming<'a> {
/// let (count, address) = socket.recv_from(&mut buf).unwrap();
/// println!("socket {:?} sent {:?}", address, &buf[..count]);
/// ```
#[stable(feature = "unix_socket", since = "1.10.0")]
pub struct UnixDatagram(Socket);
#[stable(feature = "unix_socket", since = "1.10.0")]
impl fmt::Debug for UnixDatagram {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let mut builder = fmt.debug_struct("UnixDatagram");
@ -533,6 +570,7 @@ impl fmt::Debug for UnixDatagram {
impl UnixDatagram {
/// Creates a Unix datagram socket bound to the given path.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
fn inner(path: &Path) -> io::Result<UnixDatagram> {
unsafe {
@ -548,6 +586,7 @@ impl UnixDatagram {
}
/// Creates a Unix Datagram socket which is not bound to any address.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn unbound() -> io::Result<UnixDatagram> {
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
Ok(UnixDatagram(inner))
@ -556,6 +595,7 @@ impl UnixDatagram {
/// Create an unnamed pair of connected sockets.
///
/// Returns two `UnixDatagrams`s which are connected to each other.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
Ok((UnixDatagram(i1), UnixDatagram(i2)))
@ -565,6 +605,7 @@ impl UnixDatagram {
///
/// The `send` method may be used to send data to the specified address.
/// `recv` and `recv_from` will only receive data from that address.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
unsafe {
@ -583,11 +624,13 @@ impl UnixDatagram {
/// The returned `UnixListener` is a reference to the same socket that this
/// object references. Both handles can be used to accept incoming
/// connections and options set on one listener will affect the other.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn try_clone(&self) -> io::Result<UnixDatagram> {
self.0.duplicate().map(UnixDatagram)
}
/// Returns the address of this socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn local_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
}
@ -595,6 +638,7 @@ impl UnixDatagram {
/// Returns the address of this socket's peer.
///
/// The `connect` method will connect the socket to a peer.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
}
@ -603,6 +647,7 @@ impl UnixDatagram {
///
/// On success, returns the number of bytes read and the address from
/// whence the data came.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
let mut count = 0;
let addr = SocketAddr::new(|addr, len| {
@ -629,6 +674,7 @@ impl UnixDatagram {
/// Receives data from the socket.
///
/// On success, returns the number of bytes read.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
@ -636,6 +682,7 @@ impl UnixDatagram {
/// Sends data on the socket to the specified address.
///
/// On success, returns the number of bytes written.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
unsafe {
@ -659,6 +706,7 @@ impl UnixDatagram {
/// will return an error if the socket has not already been connected.
///
/// On success, returns the number of bytes written.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf)
}
@ -668,6 +716,7 @@ impl UnixDatagram {
/// If the provided value is `None`, then `recv` and `recv_from` calls will
/// block indefinitely. It is an error to pass the zero `Duration` to this
/// method.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
}
@ -677,26 +726,31 @@ impl UnixDatagram {
/// If the provided value is `None`, then `send` and `send_to` calls will
/// block indefinitely. It is an error to pass the zero `Duration` to this
/// method.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
}
/// Returns the read timeout of this socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
self.0.timeout(libc::SO_RCVTIMEO)
}
/// Returns the write timeout of this socket.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
self.0.timeout(libc::SO_SNDTIMEO)
}
/// Moves the socket into or out of nonblocking mode.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
self.0.set_nonblocking(nonblocking)
}
/// Returns the value of the `SO_ERROR` option.
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
self.0.take_error()
}
@ -706,23 +760,27 @@ impl UnixDatagram {
/// This function will cause all pending and future I/O calls on the
/// specified portions to immediately return with an appropriate value
/// (see the documentation of `Shutdown`).
#[stable(feature = "unix_socket", since = "1.10.0")]
pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
self.0.shutdown(how)
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl AsRawFd for UnixDatagram {
fn as_raw_fd(&self) -> RawFd {
*self.0.as_inner()
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl FromRawFd for UnixDatagram {
unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
UnixDatagram(Socket::from_inner(fd))
}
}
#[stable(feature = "unix_socket", since = "1.10.0")]
impl IntoRawFd for UnixDatagram {
fn into_raw_fd(self) -> RawFd {
self.0.into_inner()

View File

@ -100,31 +100,6 @@ impl FileAttr {
}
}
#[cfg(any(target_os = "ios", target_os = "macos"))]
// FIXME: update SystemTime to store a timespec and don't lose precision
impl FileAttr {
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timeval {
tv_sec: self.stat.st_mtime,
tv_usec: (self.stat.st_mtime_nsec / 1000) as libc::suseconds_t,
}))
}
pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timeval {
tv_sec: self.stat.st_atime,
tv_usec: (self.stat.st_atime_nsec / 1000) as libc::suseconds_t,
}))
}
pub fn created(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timeval {
tv_sec: self.stat.st_birthtime,
tv_usec: (self.stat.st_birthtime_nsec / 1000) as libc::suseconds_t,
}))
}
}
#[cfg(target_os = "netbsd")]
impl FileAttr {
pub fn modified(&self) -> io::Result<SystemTime> {
@ -149,7 +124,7 @@ impl FileAttr {
}
}
#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "netbsd")))]
#[cfg(not(target_os = "netbsd"))]
impl FileAttr {
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
@ -167,7 +142,9 @@ impl FileAttr {
#[cfg(any(target_os = "bitrig",
target_os = "freebsd",
target_os = "openbsd"))]
target_os = "openbsd",
target_os = "macos",
target_os = "ios"))]
pub fn created(&self) -> io::Result<SystemTime> {
Ok(SystemTime::from(libc::timespec {
tv_sec: self.stat.st_birthtime as libc::time_t,
@ -177,7 +154,9 @@ impl FileAttr {
#[cfg(not(any(target_os = "bitrig",
target_os = "freebsd",
target_os = "openbsd")))]
target_os = "openbsd",
target_os = "macos",
target_os = "ios")))]
pub fn created(&self) -> io::Result<SystemTime> {
Err(io::Error::new(io::ErrorKind::Other,
"creation time is not available on this platform \

View File

@ -27,13 +27,13 @@ use path::{self, PathBuf};
use ptr;
use slice;
use str;
use sync::StaticMutex;
use sys_common::mutex::Mutex;
use sys::cvt;
use sys::fd;
use vec;
const TMPBUF_SZ: usize = 128;
static ENV_LOCK: StaticMutex = StaticMutex::new();
static ENV_LOCK: Mutex = Mutex::new();
/// Returns the platform-specific value of errno
#[cfg(not(target_os = "dragonfly"))]
@ -434,10 +434,11 @@ pub unsafe fn environ() -> *mut *const *const c_char {
/// Returns a vector of (variable, value) byte-vector pairs for all the
/// environment variables of the current process.
pub fn env() -> Env {
let _g = ENV_LOCK.lock();
return unsafe {
unsafe {
ENV_LOCK.lock();
let mut environ = *environ();
if environ == ptr::null() {
ENV_LOCK.unlock();
panic!("os::env() failure getting env string from OS: {}",
io::Error::last_os_error());
}
@ -448,8 +449,13 @@ pub fn env() -> Env {
}
environ = environ.offset(1);
}
Env { iter: result.into_iter(), _dont_send_or_sync_me: ptr::null_mut() }
};
let ret = Env {
iter: result.into_iter(),
_dont_send_or_sync_me: ptr::null_mut(),
};
ENV_LOCK.unlock();
return ret
}
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
// Strategy (copied from glibc): Variable name and value are separated
@ -471,32 +477,40 @@ pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
let k = CString::new(k.as_bytes())?;
let _g = ENV_LOCK.lock();
Ok(unsafe {
unsafe {
ENV_LOCK.lock();
let s = libc::getenv(k.as_ptr()) as *const _;
if s.is_null() {
let ret = if s.is_null() {
None
} else {
Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
}
})
};
ENV_LOCK.unlock();
return Ok(ret)
}
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
let k = CString::new(k.as_bytes())?;
let v = CString::new(v.as_bytes())?;
let _g = ENV_LOCK.lock();
cvt(unsafe {
libc::setenv(k.as_ptr(), v.as_ptr(), 1)
}).map(|_| ())
unsafe {
ENV_LOCK.lock();
let ret = cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(|_| ());
ENV_LOCK.unlock();
return ret
}
}
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
let nbuf = CString::new(n.as_bytes())?;
let _g = ENV_LOCK.lock();
cvt(unsafe {
libc::unsetenv(nbuf.as_ptr())
}).map(|_| ())
unsafe {
ENV_LOCK.lock();
let ret = cvt(libc::unsetenv(nbuf.as_ptr())).map(|_| ());
ENV_LOCK.unlock();
return ret
}
}
pub fn page_size() -> usize {

View File

@ -8,37 +8,129 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cmp::Ordering;
use time::Duration;
use libc;
pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
const NSEC_PER_SEC: u64 = 1_000_000_000;
#[derive(Copy, Clone)]
struct Timespec {
t: libc::timespec,
}
impl Timespec {
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
(self.t.tv_nsec - other.t.tv_nsec) as u32)
} else {
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
other.t.tv_nsec as u32)
})
} else {
match other.sub_timespec(self) {
Ok(d) => Err(d),
Err(d) => Ok(d),
}
}
}
fn add_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
let mut secs = secs.expect("overflow when adding duration to time");
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
if nsec >= NSEC_PER_SEC as u32 {
nsec -= NSEC_PER_SEC as u32;
secs = secs.checked_add(1).expect("overflow when adding \
duration to time");
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_nsec: nsec as libc::c_long,
},
}
}
fn sub_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
let mut secs = secs.expect("overflow when subtracting duration \
from time");
// Similar to above, nanos can't overflow.
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
if nsec < 0 {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1).expect("overflow when subtracting \
duration from time");
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_nsec: nsec as libc::c_long,
},
}
}
}
impl PartialEq for Timespec {
fn eq(&self, other: &Timespec) -> bool {
self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
}
}
impl Eq for Timespec {}
impl PartialOrd for Timespec {
fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Timespec {
fn cmp(&self, other: &Timespec) -> Ordering {
let me = (self.t.tv_sec, self.t.tv_nsec);
let other = (other.t.tv_sec, other.t.tv_nsec);
me.cmp(&other)
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
mod inner {
use cmp::Ordering;
use fmt;
use libc;
use super::NSEC_PER_SEC;
use sync::Once;
use sys::cvt;
use sys_common::mul_div_u64;
use time::Duration;
const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;
use super::NSEC_PER_SEC;
use super::Timespec;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Instant {
t: u64
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SystemTime {
t: libc::timeval,
t: Timespec,
}
pub const UNIX_EPOCH: SystemTime = SystemTime {
t: libc::timeval {
tv_sec: 0,
tv_usec: 0,
t: Timespec {
t: libc::timespec {
tv_sec: 0,
tv_nsec: 0,
},
},
};
@ -72,113 +164,50 @@ mod inner {
impl SystemTime {
pub fn now() -> SystemTime {
let mut s = SystemTime {
t: libc::timeval {
tv_sec: 0,
tv_usec: 0,
},
let mut s = libc::timeval {
tv_sec: 0,
tv_usec: 0,
};
cvt(unsafe {
libc::gettimeofday(&mut s.t, 0 as *mut _)
libc::gettimeofday(&mut s, 0 as *mut _)
}).unwrap();
return s
return SystemTime::from(s)
}
pub fn sub_time(&self, other: &SystemTime)
-> Result<Duration, Duration> {
if self >= other {
Ok(if self.t.tv_usec >= other.t.tv_usec {
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
((self.t.tv_usec -
other.t.tv_usec) as u32) * 1000)
} else {
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
(self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
other.t.tv_usec as u32) * 1000)
})
} else {
match other.sub_time(self) {
Ok(d) => Err(d),
Err(d) => Ok(d),
}
}
self.t.sub_timespec(&other.t)
}
pub fn add_duration(&self, other: &Duration) -> SystemTime {
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
let mut secs = secs.expect("overflow when adding duration to time");
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
if usec >= USEC_PER_SEC as u32 {
usec -= USEC_PER_SEC as u32;
secs = secs.checked_add(1).expect("overflow when adding \
duration to time");
}
SystemTime {
t: libc::timeval {
tv_sec: secs as libc::time_t,
tv_usec: usec as libc::suseconds_t,
},
}
SystemTime { t: self.t.add_duration(other) }
}
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
let mut secs = secs.expect("overflow when subtracting duration \
from time");
// Similar to above, nanos can't overflow.
let mut usec = self.t.tv_usec as i32 -
(other.subsec_nanos() / 1000) as i32;
if usec < 0 {
usec += USEC_PER_SEC as i32;
secs = secs.checked_sub(1).expect("overflow when subtracting \
duration from time");
}
SystemTime {
t: libc::timeval {
tv_sec: secs as libc::time_t,
tv_usec: usec as libc::suseconds_t,
},
}
SystemTime { t: self.t.sub_duration(other) }
}
}
impl From<libc::timeval> for SystemTime {
fn from(t: libc::timeval) -> SystemTime {
SystemTime { t: t }
SystemTime::from(libc::timespec {
tv_sec: t.tv_sec,
tv_nsec: (t.tv_usec * 1000) as libc::c_long,
})
}
}
impl PartialEq for SystemTime {
fn eq(&self, other: &SystemTime) -> bool {
self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec
}
}
impl Eq for SystemTime {}
impl PartialOrd for SystemTime {
fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for SystemTime {
fn cmp(&self, other: &SystemTime) -> Ordering {
let me = (self.t.tv_sec, self.t.tv_usec);
let other = (other.t.tv_sec, other.t.tv_usec);
me.cmp(&other)
impl From<libc::timespec> for SystemTime {
fn from(t: libc::timespec) -> SystemTime {
SystemTime { t: Timespec { t: t } }
}
}
impl fmt::Debug for SystemTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("SystemTime")
.field("tv_sec", &self.t.tv_sec)
.field("tv_usec", &self.t.tv_usec)
.field("tv_sec", &self.t.t.tv_sec)
.field("tv_nsec", &self.t.t.tv_nsec)
.finish()
}
}
@ -209,17 +238,12 @@ mod inner {
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
mod inner {
use cmp::Ordering;
use fmt;
use libc;
use super::NSEC_PER_SEC;
use sys::cvt;
use time::Duration;
#[derive(Copy, Clone)]
struct Timespec {
t: libc::timespec,
}
use super::Timespec;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Instant {
@ -242,7 +266,7 @@ mod inner {
impl Instant {
pub fn now() -> Instant {
Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
Instant { t: now(libc::CLOCK_MONOTONIC) }
}
pub fn sub_instant(&self, other: &Instant) -> Duration {
@ -271,7 +295,7 @@ mod inner {
impl SystemTime {
pub fn now() -> SystemTime {
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
SystemTime { t: now(libc::CLOCK_REALTIME) }
}
pub fn sub_time(&self, other: &SystemTime)
@ -308,98 +332,16 @@ mod inner {
#[cfg(target_os = "dragonfly")]
pub type clock_t = libc::c_ulong;
impl Timespec {
pub fn now(clock: clock_t) -> Timespec {
let mut t = Timespec {
t: libc::timespec {
tv_sec: 0,
tv_nsec: 0,
}
};
cvt(unsafe {
libc::clock_gettime(clock, &mut t.t)
}).unwrap();
t
}
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
(self.t.tv_nsec - other.t.tv_nsec) as u32)
} else {
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
other.t.tv_nsec as u32)
})
} else {
match other.sub_timespec(self) {
Ok(d) => Err(d),
Err(d) => Ok(d),
}
fn now(clock: clock_t) -> Timespec {
let mut t = Timespec {
t: libc::timespec {
tv_sec: 0,
tv_nsec: 0,
}
}
fn add_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
let mut secs = secs.expect("overflow when adding duration to time");
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
if nsec >= NSEC_PER_SEC as u32 {
nsec -= NSEC_PER_SEC as u32;
secs = secs.checked_add(1).expect("overflow when adding \
duration to time");
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_nsec: nsec as libc::c_long,
},
}
}
fn sub_duration(&self, other: &Duration) -> Timespec {
let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
let mut secs = secs.expect("overflow when subtracting duration \
from time");
// Similar to above, nanos can't overflow.
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
if nsec < 0 {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1).expect("overflow when subtracting \
duration from time");
}
Timespec {
t: libc::timespec {
tv_sec: secs as libc::time_t,
tv_nsec: nsec as libc::c_long,
},
}
}
}
impl PartialEq for Timespec {
fn eq(&self, other: &Timespec) -> bool {
self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
}
}
impl Eq for Timespec {}
impl PartialOrd for Timespec {
fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Timespec {
fn cmp(&self, other: &Timespec) -> Ordering {
let me = (self.t.tv_sec, self.t.tv_nsec);
let other = (other.t.tv_sec, other.t.tv_nsec);
me.cmp(&other)
}
};
cvt(unsafe {
libc::clock_gettime(clock, &mut t.t)
}).unwrap();
t
}
}

View File

@ -19,9 +19,7 @@ use sys;
use sys_common::{AsInnerMut, AsInner};
/// Windows-specific extensions to `OpenOptions`
#[unstable(feature = "open_options_ext",
reason = "may require more thought/methods",
issue = "27720")]
#[stable(feature = "open_options_ext", since = "1.10.0")]
pub trait OpenOptionsExt {
/// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
/// with the specified value.
@ -34,7 +32,6 @@ pub trait OpenOptionsExt {
/// # Examples
///
/// ```no_run
/// #![feature(open_options_ext)]
/// use std::fs::OpenOptions;
/// use std::os::windows::fs::OpenOptionsExt;
///
@ -42,6 +39,7 @@ pub trait OpenOptionsExt {
/// // to call `stat()` on the file
/// let file = OpenOptions::new().access_mode(0).open("foo.txt");
/// ```
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn access_mode(&mut self, access: u32) -> &mut Self;
/// Overrides the `dwShareMode` argument to the call to `CreateFile` with
@ -55,7 +53,6 @@ pub trait OpenOptionsExt {
/// # Examples
///
/// ```no_run
/// #![feature(open_options_ext)]
/// use std::fs::OpenOptions;
/// use std::os::windows::fs::OpenOptionsExt;
///
@ -65,6 +62,7 @@ pub trait OpenOptionsExt {
/// .share_mode(0)
/// .open("foo.txt");
/// ```
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn share_mode(&mut self, val: u32) -> &mut Self;
/// Sets extra flags for the `dwFileFlags` argument to the call to
@ -88,9 +86,7 @@ pub trait OpenOptionsExt {
/// }
/// let file = options.open("foo.txt");
/// ```
#[unstable(feature = "expand_open_options",
reason = "recently added",
issue = "30014")]
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn custom_flags(&mut self, flags: u32) -> &mut Self;
/// Sets the `dwFileAttributes` argument to the call to `CreateFile2` to
@ -111,7 +107,6 @@ pub trait OpenOptionsExt {
/// # Examples
///
/// ```rust,ignore
/// #![feature(open_options_ext)]
/// extern crate winapi;
/// use std::fs::OpenOptions;
/// use std::os::windows::fs::OpenOptionsExt;
@ -120,17 +115,17 @@ pub trait OpenOptionsExt {
/// .attributes(winapi::FILE_ATTRIBUTE_HIDDEN)
/// .open("foo.txt");
/// ```
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn attributes(&mut self, val: u32) -> &mut Self;
/// Sets the `dwSecurityQosFlags` argument to the call to `CreateFile2` to
/// the specified value (or combines it with `custom_flags` and `attributes`
/// to set the `dwFlagsAndAttributes` for `CreateFile`).
#[stable(feature = "open_options_ext", since = "1.10.0")]
fn security_qos_flags(&mut self, flags: u32) -> &mut OpenOptions;
}
#[unstable(feature = "open_options_ext",
reason = "may require more thought/methods",
issue = "27720")]
#[stable(feature = "open_options_ext", since = "1.10.0")]
impl OpenOptionsExt for OpenOptions {
fn access_mode(&mut self, access: u32) -> &mut OpenOptions {
self.as_inner_mut().access_mode(access); self

View File

@ -24,7 +24,7 @@ use mem;
use os::windows::ffi::OsStrExt;
use path::Path;
use ptr;
use sync::StaticMutex;
use sys::mutex::Mutex;
use sys::c;
use sys::fs::{OpenOptions, File};
use sys::handle::Handle;
@ -75,6 +75,10 @@ pub struct StdioPipes {
pub stderr: Option<AnonPipe>,
}
struct DropGuard<'a> {
lock: &'a Mutex,
}
impl Command {
pub fn new(program: &OsStr) -> Command {
Command {
@ -173,8 +177,8 @@ impl Command {
//
// For more information, msdn also has an article about this race:
// http://support.microsoft.com/kb/315939
static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new();
let _lock = CREATE_PROCESS_LOCK.lock();
static CREATE_PROCESS_LOCK: Mutex = Mutex::new();
let _guard = DropGuard::new(&CREATE_PROCESS_LOCK);
let mut pipes = StdioPipes {
stdin: None,
@ -224,6 +228,23 @@ impl fmt::Debug for Command {
}
}
impl<'a> DropGuard<'a> {
fn new(lock: &'a Mutex) -> DropGuard<'a> {
unsafe {
lock.lock();
DropGuard { lock: lock }
}
}
}
impl<'a> Drop for DropGuard<'a> {
fn drop(&mut self) {
unsafe {
self.lock.unlock();
}
}
}
impl Stdio {
fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>)
-> io::Result<Handle> {