diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-05-12 12:48:14 +1200 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-05-12 12:48:14 +1200 |
| commit | e0216fcc42d5f4961d07378a783c87814097015f (patch) | |
| tree | e5f503c129942a2b7c2815b1c8e4db85b5bbcf1b /src/libstd/sys/common | |
| parent | aa5ca282b20391c6df51fdfa94e0de5672ccfac1 (diff) | |
| parent | 750f2c63f2737305d33288303cdecb7a470a7922 (diff) | |
| download | rust-e0216fcc42d5f4961d07378a783c87814097015f.tar.gz rust-e0216fcc42d5f4961d07378a783c87814097015f.zip | |
Merge branch 'master' into
Diffstat (limited to 'src/libstd/sys/common')
| -rw-r--r-- | src/libstd/sys/common/helper_thread.rs | 170 | ||||
| -rw-r--r-- | src/libstd/sys/common/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sys/common/net.rs (renamed from src/libstd/sys/common/net2.rs) | 47 | ||||
| -rw-r--r-- | src/libstd/sys/common/poison.rs | 11 | ||||
| -rw-r--r-- | src/libstd/sys/common/remutex.rs | 18 | ||||
| -rw-r--r-- | src/libstd/sys/common/stack.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys/common/wtf8.rs | 8 |
7 files changed, 71 insertions, 189 deletions
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs deleted file mode 100644 index 34a58f6c83a..00000000000 --- a/src/libstd/sys/common/helper_thread.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <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. - -//! Implementation of the helper thread for the timer module -//! -//! This module contains the management necessary for the timer worker thread. -//! This thread is responsible for performing the send()s on channels for timers -//! that are using channels instead of a blocking call. -//! -//! The timer thread is lazily initialized, and it's shut down via the -//! `shutdown` function provided. It must be maintained as an invariant that -//! `shutdown` is only called when the entire program is finished. No new timers -//! can be created in the future and there must be no active timers at that -//! time. - -use prelude::v1::*; - -use boxed; -use cell::UnsafeCell; -use rt; -use sync::{StaticMutex, StaticCondvar}; -use sync::mpsc::{channel, Sender, Receiver}; -use sys::helper_signal; - -use thread; - -/// A structure for management of a helper thread. -/// -/// This is generally a static structure which tracks the lifetime of a helper -/// thread. -/// -/// The fields of this helper are all public, but they should not be used, this -/// is for static initialization. -pub struct Helper<M:Send> { - /// Internal lock which protects the remaining fields - pub lock: StaticMutex, - pub cond: StaticCondvar, - - // You'll notice that the remaining fields are UnsafeCell<T>, and this is - // because all helper thread operations are done through &self, but we need - // these to be mutable (once `lock` is held). - - /// Lazily allocated channel to send messages to the helper thread. - pub chan: UnsafeCell<*mut Sender<M>>, - - /// OS handle used to wake up a blocked helper thread - pub signal: UnsafeCell<usize>, - - /// Flag if this helper thread has booted and been initialized yet. - pub initialized: UnsafeCell<bool>, - - /// Flag if this helper thread has shut down - pub shutdown: UnsafeCell<bool>, -} - -unsafe impl<M:Send> Send for Helper<M> { } - -unsafe impl<M:Send> Sync for Helper<M> { } - -struct RaceBox(helper_signal::signal); - -unsafe impl Send for RaceBox {} -unsafe impl Sync for RaceBox {} - -macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => ( - static $name: Helper<$m> = Helper { - lock: ::sync::MUTEX_INIT, - cond: ::sync::CONDVAR_INIT, - chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, - signal: ::cell::UnsafeCell { value: 0 }, - initialized: ::cell::UnsafeCell { value: false }, - shutdown: ::cell::UnsafeCell { value: false }, - }; -) } - -impl<M: Send> Helper<M> { - /// Lazily boots a helper thread, becoming a no-op if the helper has already - /// been spawned. - /// - /// This function will check to see if the thread has been initialized, and - /// if it has it returns quickly. If initialization has not happened yet, - /// the closure `f` will be run (inside of the initialization lock) and - /// passed to the helper thread in a separate task. - /// - /// This function is safe to be called many times. - pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where - T: Send + 'static, - F: FnOnce() -> T, - { - unsafe { - let _guard = self.lock.lock().unwrap(); - if *self.chan.get() as usize == 0 { - let (tx, rx) = channel(); - *self.chan.get() = boxed::into_raw(box tx); - let (receive, send) = helper_signal::new(); - *self.signal.get() = send as usize; - - let receive = RaceBox(receive); - - let t = f(); - thread::spawn(move || { - helper(receive.0, rx, t); - let _g = self.lock.lock().unwrap(); - *self.shutdown.get() = true; - self.cond.notify_one() - }); - - let _ = rt::at_exit(move || { self.shutdown() }); - *self.initialized.get() = true; - } else if *self.chan.get() as usize == 1 { - panic!("cannot continue usage after shutdown"); - } - } - } - - /// Sends a message to a spawned worker thread. - /// - /// This is only valid if the worker thread has previously booted - pub fn send(&'static self, msg: M) { - unsafe { - 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 - // send the message. - assert!(*self.chan.get() as usize != 0); - assert!(*self.chan.get() as usize != 1, - "cannot continue usage after shutdown"); - (**self.chan.get()).send(msg).unwrap(); - helper_signal::signal(*self.signal.get() as helper_signal::signal); - } - } - - fn shutdown(&'static self) { - unsafe { - // 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 mut guard = self.lock.lock().unwrap(); - - let ptr = *self.chan.get(); - if ptr as usize == 1 { - panic!("cannot continue usage after shutdown"); - } - // Close the channel by destroying it - let chan = Box::from_raw(*self.chan.get()); - *self.chan.get() = 1 as *mut Sender<M>; - drop(chan); - helper_signal::signal(*self.signal.get() as helper_signal::signal); - - // Wait for the child to exit - while !*self.shutdown.get() { - guard = self.cond.wait(guard).unwrap(); - } - drop(guard); - - // Clean up after ourselves - self.lock.destroy(); - helper_signal::close(*self.signal.get() as helper_signal::signal); - *self.signal.get() = 0; - } - } -} diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs index 95294b813ea..b528575bbed 100644 --- a/src/libstd/sys/common/mod.rs +++ b/src/libstd/sys/common/mod.rs @@ -15,7 +15,7 @@ use prelude::v1::*; pub mod backtrace; pub mod condvar; pub mod mutex; -pub mod net2; +pub mod net; pub mod poison; pub mod remutex; pub mod rwlock; diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net.rs index 2b2c31d92ed..7da7071670a 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net.rs @@ -11,6 +11,7 @@ use prelude::v1::*; use ffi::{CStr, CString}; +use fmt; use io::{self, Error, ErrorKind}; use libc::{self, c_int, c_char, c_void, socklen_t}; use mem; @@ -268,6 +269,24 @@ impl FromInner<Socket> for TcpStream { } } +impl fmt::Debug for TcpStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpStream"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + if let Ok(peer) = self.peer_addr() { + res = res.field("peer", &peer); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} + //////////////////////////////////////////////////////////////////////////////// // TCP listeners //////////////////////////////////////////////////////////////////////////////// @@ -327,6 +346,20 @@ impl FromInner<Socket> for TcpListener { } } +impl fmt::Debug for TcpListener { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpListener"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} + //////////////////////////////////////////////////////////////////////////////// // UDP //////////////////////////////////////////////////////////////////////////////// @@ -445,3 +478,17 @@ impl FromInner<Socket> for UdpSocket { UdpSocket { inner: socket } } } + +impl fmt::Debug for UdpSocket { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("UdpSocket"); + + if let Ok(addr) = self.socket_addr() { + res = res.field("addr", &addr); + } + + let name = if cfg!(windows) {"socket"} else {"fd"}; + res = res.field(name, &self.inner.as_inner()); + res.finish() + } +} diff --git a/src/libstd/sys/common/poison.rs b/src/libstd/sys/common/poison.rs index 6deb4a48007..67679c11a98 100644 --- a/src/libstd/sys/common/poison.rs +++ b/src/libstd/sys/common/poison.rs @@ -10,6 +10,7 @@ use prelude::v1::*; +use marker::Reflect; use cell::UnsafeCell; use error::{Error}; use fmt; @@ -54,7 +55,7 @@ pub struct Guard { /// 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 +/// Both Mutexes and RwLocks are poisoned whenever a thread 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. @@ -67,7 +68,7 @@ pub struct PoisonError<T> { /// `try_lock` method. #[stable(feature = "rust1", since = "1.0.0")] pub enum TryLockError<T> { - /// The lock could not be acquired because another task failed while holding + /// The lock could not be acquired because another thread failed while holding /// the lock. #[stable(feature = "rust1", since = "1.0.0")] Poisoned(PoisonError<T>), @@ -109,7 +110,7 @@ impl<T> fmt::Display for PoisonError<T> { } } -impl<T: Send> Error for PoisonError<T> { +impl<T: Send + Reflect> Error for PoisonError<T> { fn description(&self) -> &str { "poisoned lock: another task failed inside" } @@ -155,13 +156,13 @@ impl<T> fmt::Debug for TryLockError<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Send> fmt::Display for TryLockError<T> { +impl<T: Send + Reflect> fmt::Display for TryLockError<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.description().fmt(f) } } -impl<T: Send> Error for TryLockError<T> { +impl<T: Send + Reflect> Error for TryLockError<T> { fn description(&self) -> &str { match *self { TryLockError::Poisoned(ref p) => p.description(), diff --git a/src/libstd/sys/common/remutex.rs b/src/libstd/sys/common/remutex.rs index 48c74b8d89e..1a467580672 100644 --- a/src/libstd/sys/common/remutex.rs +++ b/src/libstd/sys/common/remutex.rs @@ -19,9 +19,9 @@ use sys::mutex as sys; /// A re-entrant mutual exclusion /// -/// This mutex will block *other* threads waiting for the lock to become available. The thread -/// which has already locked the mutex can lock it multiple times without blocking, preventing a -/// common source of deadlocks. +/// This mutex will block *other* threads waiting for the lock to become +/// available. The thread which has already locked the mutex can lock it +/// multiple times without blocking, preventing a common source of deadlocks. pub struct ReentrantMutex<T> { inner: Box<sys::ReentrantMutex>, poison: poison::Flag, @@ -51,10 +51,14 @@ impl<'a, T> !marker::Send for ReentrantMutexGuard<'a, T> {} impl<T> ReentrantMutex<T> { /// Creates a new reentrant mutex in an unlocked state. pub fn new(t: T) -> ReentrantMutex<T> { - ReentrantMutex { - inner: box unsafe { sys::ReentrantMutex::new() }, - poison: poison::FLAG_INIT, - data: t, + unsafe { + let mut mutex = ReentrantMutex { + inner: box sys::ReentrantMutex::uninitialized(), + poison: poison::FLAG_INIT, + data: t, + }; + mutex.inner.init(); + return mutex } } diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs index 8dc3407db77..fadeebc8150 100644 --- a/src/libstd/sys/common/stack.rs +++ b/src/libstd/sys/common/stack.rs @@ -11,13 +11,13 @@ //! Rust stack-limit management //! //! Currently Rust uses a segmented-stack-like scheme in order to detect stack -//! overflow for rust tasks. In this scheme, the prologue of all functions are +//! overflow for rust threads. In this scheme, the prologue of all functions are //! preceded with a check to see whether the current stack limits are being //! exceeded. //! //! This module provides the functionality necessary in order to manage these //! stack limits (which are stored in platform-specific locations). The -//! functions here are used at the borders of the task lifetime in order to +//! functions here are used at the borders of the thread lifetime in order to //! manage these limits. //! //! This function is an unstable module because this scheme for stack overflow diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index 56a952e6a7e..cb9239ed7ba 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -161,7 +161,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: Vec::with_capacity(n) } } - /// Creates a WTF-8 string from an UTF-8 `String`. + /// Creates a WTF-8 string from a UTF-8 `String`. /// /// This takes ownership of the `String` and does not copy. /// @@ -171,7 +171,7 @@ impl Wtf8Buf { Wtf8Buf { bytes: string.into_bytes() } } - /// Creates a WTF-8 string from an UTF-8 `&str` slice. + /// Creates a WTF-8 string from a UTF-8 `&str` slice. /// /// This copies the content of the slice. /// @@ -245,7 +245,7 @@ impl Wtf8Buf { self.bytes.capacity() } - /// Append an UTF-8 slice at the end of the string. + /// Append a UTF-8 slice at the end of the string. #[inline] pub fn push_str(&mut self, other: &str) { self.bytes.push_all(other.as_bytes()) @@ -527,7 +527,7 @@ impl Wtf8 { } /// Lossily converts the string to UTF-8. - /// Returns an UTF-8 `&str` slice if the contents are well-formed in UTF-8. + /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8. /// /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”). /// |
