diff options
| author | bors <bors@rust-lang.org> | 2017-05-10 17:10:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-05-10 17:10:13 +0000 |
| commit | 978d2cfee1ee9da704c960c8047e978a7003b582 (patch) | |
| tree | e74ba8f6a9d7b0b7bfa6a313ed7e1828219be6f3 /src/libstd | |
| parent | 25a161765fb90f2bfc78bda8fef944048e72bd26 (diff) | |
| parent | 19f1146ded4f7cfd4dc2720dcee49d9464a92429 (diff) | |
| download | rust-978d2cfee1ee9da704c960c8047e978a7003b582.tar.gz rust-978d2cfee1ee9da704c960c8047e978a7003b582.zip | |
Auto merge of #41887 - steveklabnik:rollup, r=steveklabnik
Rollup of 5 pull requests - Successful merges: #41531, #41536, #41809, #41854, #41886 - Failed merges:
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/path.rs | 36 | ||||
| -rw-r--r-- | src/libstd/thread/mod.rs | 214 |
2 files changed, 182 insertions, 68 deletions
diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 9d66430bc93..f4b9a8972e3 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -51,10 +51,17 @@ //! ``` //! use std::path::PathBuf; //! +//! // This way works... //! let mut path = PathBuf::from("c:\\"); +//! //! path.push("windows"); //! path.push("system32"); +//! //! path.set_extension("dll"); +//! +//! // ... but push is best used if you don't know everything up +//! // front. If you do, this way is better: +//! let path: PathBuf = ["c:\\", "windows", "system32.dll"].iter().collect(); //! ``` //! //! [`Component`]: ../../std/path/enum.Component.html @@ -63,6 +70,7 @@ //! [`Path`]: ../../std/path/struct.Path.html //! [`push`]: ../../std/path/struct.PathBuf.html#method.push //! [`String`]: ../../std/string/struct.String.html +//! //! [`str`]: ../../std/primitive.str.html //! [`OsString`]: ../../std/ffi/struct.OsString.html //! [`OsStr`]: ../../std/ffi/struct.OsStr.html @@ -1036,14 +1044,40 @@ impl<'a> cmp::Ord for Components<'a> { /// /// # Examples /// +/// You can use [`push`] to build up a `PathBuf` from +/// components: +/// /// ``` /// use std::path::PathBuf; /// -/// let mut path = PathBuf::from("c:\\"); +/// let mut path = PathBuf::new(); +/// +/// path.push(r"C:\"); /// path.push("windows"); /// path.push("system32"); +/// /// path.set_extension("dll"); /// ``` +/// +/// However, [`push`] is best used for dynamic situations. This is a better way +/// to do this when you know all of the components ahead of time: +/// +/// ``` +/// use std::path::PathBuf; +/// +/// let path: PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect(); +/// ``` +/// +/// We can still do better than this! Since these are all strings, we can use +/// `From::from`: +/// +/// ``` +/// use std::path::PathBuf; +/// +/// let path = PathBuf::from(r"C:\windows\system32.dll"); +/// ``` +/// +/// Which method works best depends on what kind of situation you're in. #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct PathBuf { diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 4432f898e04..230c60baf8b 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -96,41 +96,6 @@ //! The [`thread::current`] function is available even for threads not spawned //! by the APIs of this module. //! -//! ## Blocking support: park and unpark -//! -//! Every thread is equipped with some basic low-level blocking support, via the -//! [`thread::park`][`park`] function and [`thread::Thread::unpark()`][`unpark`] -//! method. [`park`] blocks the current thread, which can then be resumed from -//! another thread by calling the [`unpark`] method on the blocked thread's handle. -//! -//! Conceptually, each [`Thread`] handle has an associated token, which is -//! initially not present: -//! -//! * The [`thread::park`][`park`] function blocks the current thread unless or until -//! the token is available for its thread handle, at which point it atomically -//! consumes the token. It may also return *spuriously*, without consuming the -//! token. [`thread::park_timeout`] does the same, but allows specifying a -//! maximum time to block the thread for. -//! -//! * The [`unpark`] method on a [`Thread`] atomically makes the token available -//! if it wasn't already. -//! -//! In other words, each [`Thread`] acts a bit like a semaphore with initial count -//! 0, except that the semaphore is *saturating* (the count cannot go above 1), -//! and can return spuriously. -//! -//! The API is typically used by acquiring a handle to the current thread, -//! placing that handle in a shared data structure so that other threads can -//! find it, and then `park`ing. When some desired condition is met, another -//! thread calls [`unpark`] on the handle. -//! -//! The motivation for this design is twofold: -//! -//! * It avoids the need to allocate mutexes and condvars when building new -//! synchronization primitives; the threads already provide basic blocking/signaling. -//! -//! * It can be implemented very efficiently on many platforms. -//! //! ## Thread-local storage //! //! This module also provides an implementation of thread-local storage for Rust @@ -322,6 +287,8 @@ impl Builder { /// thread finishes). The join handle can be used to block on /// termination of the child thread, including recovering its panics. /// + /// For a more complete documentation see [`thread::spawn`][`spawn`]. + /// /// # Errors /// /// Unlike the [`spawn`] free function, this method yields an @@ -396,19 +363,19 @@ impl Builder { /// panics, [`join`] will return an [`Err`] containing the argument given to /// [`panic`]. /// +/// This will create a thread using default parameters of [`Builder`], if you +/// want to specify the stack size or the name of the thread, use this API +/// instead. +/// /// # Panics /// /// Panics if the OS fails to create a thread; use [`Builder::spawn`] /// to recover from such errors. /// -/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html -/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join -/// [`Err`]: ../../std/result/enum.Result.html#variant.Err -/// [`panic`]: ../../std/macro.panic.html -/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn -/// /// # Examples /// +/// Creating a thread. +/// /// ``` /// use std::thread; /// @@ -418,6 +385,54 @@ impl Builder { /// /// handler.join().unwrap(); /// ``` +/// +/// As mentioned in the module documentation, threads are usually made to +/// communicate using [`channels`], here is how it usually looks. +/// +/// This example also shows how to use `move`, in order to give ownership +/// of values to a thread. +/// +/// ``` +/// use std::thread; +/// use std::sync::mpsc::channel; +/// +/// let (tx, rx) = channel(); +/// +/// let sender = thread::spawn(move || { +/// let _ = tx.send("Hello, thread".to_owned()); +/// }); +/// +/// let receiver = thread::spawn(move || { +/// println!("{}", rx.recv().unwrap()); +/// }); +/// +/// let _ = sender.join(); +/// let _ = receiver.join(); +/// ``` +/// +/// A thread can also return a value through its [`JoinHandle`], you can use +/// this to make asynchronous computations (futures might be more appropriate +/// though). +/// +/// ``` +/// use std::thread; +/// +/// let computation = thread::spawn(|| { +/// // Some expensive computation. +/// 42 +/// }); +/// +/// let result = computation.join().unwrap(); +/// println!("{}", result); +/// ``` +/// +/// [`channels`]: ../../std/sync/mpsc/index.html +/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html +/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join +/// [`Err`]: ../../std/result/enum.Result.html#variant.Err +/// [`panic`]: ../../std/macro.panic.html +/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn +/// [`Builder`]: ../../std/thread/struct.Builder.html #[stable(feature = "rust1", since = "1.0.0")] pub fn spawn<F, T>(f: F) -> JoinHandle<T> where F: FnOnce() -> T, F: Send + 'static, T: Send + 'static @@ -568,23 +583,72 @@ pub fn sleep(dur: Duration) { /// Blocks unless or until the current thread's token is made available. /// -/// Every thread is equipped with some basic low-level blocking support, via -/// the `park()` function and the [`unpark`][unpark] method. These can be -/// used as a more CPU-efficient implementation of a spinlock. +/// A call to `park` does not guarantee that the thread will remain parked +/// forever, and callers should be prepared for this possibility. /// -/// [unpark]: struct.Thread.html#method.unpark +/// # park and unpark +/// +/// Every thread is equipped with some basic low-level blocking support, via the +/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`] +/// method. [`park`] blocks the current thread, which can then be resumed from +/// another thread by calling the [`unpark`] method on the blocked thread's +/// handle. +/// +/// Conceptually, each [`Thread`] handle has an associated token, which is +/// initially not present: +/// +/// * The [`thread::park`][`park`] function blocks the current thread unless or +/// until the token is available for its thread handle, at which point it +/// atomically consumes the token. It may also return *spuriously*, without +/// consuming the token. [`thread::park_timeout`] does the same, but allows +/// specifying a maximum time to block the thread for. +/// +/// * The [`unpark`] method on a [`Thread`] atomically makes the token available +/// if it wasn't already. +/// +/// In other words, each [`Thread`] acts a bit like a spinlock that can be +/// locked and unlocked using `park` and `unpark`. /// /// The API is typically used by acquiring a handle to the current thread, /// placing that handle in a shared data structure so that other threads can -/// find it, and then parking (in a loop with a check for the token actually -/// being acquired). +/// find it, and then `park`ing. When some desired condition is met, another +/// thread calls [`unpark`] on the handle. /// -/// A call to `park` does not guarantee that the thread will remain parked -/// forever, and callers should be prepared for this possibility. +/// The motivation for this design is twofold: /// -/// See the [module documentation][thread] for more detail. +/// * It avoids the need to allocate mutexes and condvars when building new +/// synchronization primitives; the threads already provide basic +/// blocking/signaling. /// -/// [thread]: index.html +/// * It can be implemented very efficiently on many platforms. +/// +/// # Examples +/// +/// ``` +/// use std::thread; +/// use std::time::Duration; +/// +/// let parked_thread = thread::Builder::new() +/// .spawn(|| { +/// println!("Parking thread"); +/// thread::park(); +/// println!("Thread unparked"); +/// }) +/// .unwrap(); +/// +/// // Let some time pass for the thread to be spawned. +/// thread::sleep(Duration::from_millis(10)); +/// +/// println!("Unpark the thread"); +/// parked_thread.thread().unpark(); +/// +/// parked_thread.join().unwrap(); +/// ``` +/// +/// [`Thread`]: ../../std/thread/struct.Thread.html +/// [`park`]: ../../std/thread/fn.park.html +/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark +/// [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html // // The implementation currently uses the trivial strategy of a Mutex+Condvar // with wakeup flag, which does not actually allow spurious wakeups. In the @@ -601,21 +665,21 @@ pub fn park() { *guard = false; } -/// Use [park_timeout]. +/// Use [`park_timeout`]. /// /// Blocks unless or until the current thread's token is made available or /// the specified duration has been reached (may wake spuriously). /// -/// The semantics of this function are equivalent to `park()` except that the -/// thread will be blocked for roughly no longer than `ms`. This method -/// should not be used for precise timing due to anomalies such as +/// The semantics of this function are equivalent to [`park`] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as /// preemption or platform differences that may not cause the maximum /// amount of time waited to be precisely `ms` long. /// -/// See the [module documentation][thread] for more detail. +/// See the [park documentation][`park`] for more detail. /// -/// [thread]: index.html -/// [park_timeout]: fn.park_timeout.html +/// [`park_timeout`]: fn.park_timeout.html +/// [`park`]: ../../std/thread/fn.park.html #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")] pub fn park_timeout_ms(ms: u32) { @@ -625,13 +689,13 @@ pub fn park_timeout_ms(ms: u32) { /// Blocks unless or until the current thread's token is made available or /// the specified duration has been reached (may wake spuriously). /// -/// The semantics of this function are equivalent to `park()` except that the -/// thread will be blocked for roughly no longer than `dur`. This method -/// should not be used for precise timing due to anomalies such as +/// The semantics of this function are equivalent to [`park`][park] except +/// that the thread will be blocked for roughly no longer than `dur`. This +/// method should not be used for precise timing due to anomalies such as /// preemption or platform differences that may not cause the maximum /// amount of time waited to be precisely `dur` long. /// -/// See the module doc for more detail. +/// See the [park dococumentation][park] for more details. /// /// # Platform behavior /// @@ -656,6 +720,8 @@ pub fn park_timeout_ms(ms: u32) { /// park_timeout(timeout); /// } /// ``` +/// +/// [park]: fn.park.html #[stable(feature = "park_timeout", since = "1.4.0")] pub fn park_timeout(dur: Duration) { let thread = current(); @@ -777,22 +843,36 @@ impl Thread { /// Atomically makes the handle's token available if it is not already. /// - /// See the module doc for more detail. + /// Every thread is equipped with some basic low-level blocking support, via + /// the [`park`][park] function and the `unpark()` method. These can be + /// used as a more CPU-efficient implementation of a spinlock. + /// + /// See the [park documentation][park] for more details. /// /// # Examples /// /// ``` /// use std::thread; + /// use std::time::Duration; /// - /// let handler = thread::Builder::new() + /// let parked_thread = thread::Builder::new() /// .spawn(|| { - /// let thread = thread::current(); - /// thread.unpark(); + /// println!("Parking thread"); + /// thread::park(); + /// println!("Thread unparked"); /// }) /// .unwrap(); /// - /// handler.join().unwrap(); + /// // Let some time pass for the thread to be spawned. + /// thread::sleep(Duration::from_millis(10)); + /// + /// println!("Unpark the thread"); + /// parked_thread.thread().unpark(); + /// + /// parked_thread.join().unwrap(); /// ``` + /// + /// [park]: fn.park.html #[stable(feature = "rust1", since = "1.0.0")] pub fn unpark(&self) { let mut guard = self.inner.lock.lock().unwrap(); |
