mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
Remove argument from closure in thread::Scope::spawn.
This commit is contained in:
parent
2f8d1a835b
commit
24fe35a3e1
@ -9,23 +9,24 @@ use crate::sync::Arc;
|
||||
/// A scope to spawn scoped threads in.
|
||||
///
|
||||
/// See [`scope`] for details.
|
||||
pub struct Scope<'env> {
|
||||
pub struct Scope<'scope, 'env: 'scope> {
|
||||
data: ScopeData,
|
||||
/// Invariance over 'env, to make sure 'env cannot shrink,
|
||||
/// Invariance over 'scope, to make sure 'scope cannot shrink,
|
||||
/// which is necessary for soundness.
|
||||
///
|
||||
/// Without invariance, this would compile fine but be unsound:
|
||||
///
|
||||
/// ```compile_fail
|
||||
/// ```compile_fail,E0373
|
||||
/// #![feature(scoped_threads)]
|
||||
///
|
||||
/// std::thread::scope(|s| {
|
||||
/// s.spawn(|s| {
|
||||
/// s.spawn(|| {
|
||||
/// let a = String::from("abcd");
|
||||
/// s.spawn(|_| println!("{:?}", a)); // might run after `a` is dropped
|
||||
/// s.spawn(|| println!("{:?}", a)); // might run after `a` is dropped
|
||||
/// });
|
||||
/// });
|
||||
/// ```
|
||||
scope: PhantomData<&'scope mut &'scope ()>,
|
||||
env: PhantomData<&'env mut &'env ()>,
|
||||
}
|
||||
|
||||
@ -88,12 +89,12 @@ impl ScopeData {
|
||||
/// let mut x = 0;
|
||||
///
|
||||
/// thread::scope(|s| {
|
||||
/// s.spawn(|_| {
|
||||
/// s.spawn(|| {
|
||||
/// println!("hello from the first scoped thread");
|
||||
/// // We can borrow `a` here.
|
||||
/// dbg!(&a);
|
||||
/// });
|
||||
/// s.spawn(|_| {
|
||||
/// s.spawn(|| {
|
||||
/// println!("hello from the second scoped thread");
|
||||
/// // We can even mutably borrow `x` here,
|
||||
/// // because no other threads are using it.
|
||||
@ -109,7 +110,7 @@ impl ScopeData {
|
||||
#[track_caller]
|
||||
pub fn scope<'env, F, T>(f: F) -> T
|
||||
where
|
||||
F: FnOnce(&Scope<'env>) -> T,
|
||||
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
|
||||
{
|
||||
let scope = Scope {
|
||||
data: ScopeData {
|
||||
@ -118,6 +119,7 @@ where
|
||||
a_thread_panicked: AtomicBool::new(false),
|
||||
},
|
||||
env: PhantomData,
|
||||
scope: PhantomData,
|
||||
};
|
||||
|
||||
// Run `f`, but catch panics so we can make sure to wait for all the threads to join.
|
||||
@ -138,7 +140,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> Scope<'env> {
|
||||
impl<'scope, 'env> Scope<'scope, 'env> {
|
||||
/// Spawns a new thread within a scope, returning a [`ScopedJoinHandle`] for it.
|
||||
///
|
||||
/// Unlike non-scoped threads, threads spawned with this function may
|
||||
@ -163,10 +165,10 @@ impl<'env> Scope<'env> {
|
||||
/// to recover from such errors.
|
||||
///
|
||||
/// [`join`]: ScopedJoinHandle::join
|
||||
pub fn spawn<'scope, F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
|
||||
pub fn spawn<F, T>(&'scope self, f: F) -> ScopedJoinHandle<'scope, T>
|
||||
where
|
||||
F: FnOnce(&Scope<'env>) -> T + Send + 'env,
|
||||
T: Send + 'env,
|
||||
F: FnOnce() -> T + Send + 'scope,
|
||||
T: Send + 'scope,
|
||||
{
|
||||
Builder::new().spawn_scoped(self, f).expect("failed to spawn thread")
|
||||
}
|
||||
@ -196,7 +198,7 @@ impl Builder {
|
||||
/// thread::scope(|s| {
|
||||
/// thread::Builder::new()
|
||||
/// .name("first".to_string())
|
||||
/// .spawn_scoped(s, |_|
|
||||
/// .spawn_scoped(s, ||
|
||||
/// {
|
||||
/// println!("hello from the {:?} scoped thread", thread::current().name());
|
||||
/// // We can borrow `a` here.
|
||||
@ -205,7 +207,7 @@ impl Builder {
|
||||
/// .unwrap();
|
||||
/// thread::Builder::new()
|
||||
/// .name("second".to_string())
|
||||
/// .spawn_scoped(s, |_|
|
||||
/// .spawn_scoped(s, ||
|
||||
/// {
|
||||
/// println!("hello from the {:?} scoped thread", thread::current().name());
|
||||
/// // We can even mutably borrow `x` here,
|
||||
@ -222,14 +224,14 @@ impl Builder {
|
||||
/// ```
|
||||
pub fn spawn_scoped<'scope, 'env, F, T>(
|
||||
self,
|
||||
scope: &'scope Scope<'env>,
|
||||
scope: &'scope Scope<'scope, 'env>,
|
||||
f: F,
|
||||
) -> io::Result<ScopedJoinHandle<'scope, T>>
|
||||
where
|
||||
F: FnOnce(&Scope<'env>) -> T + Send + 'env,
|
||||
T: Send + 'env,
|
||||
F: FnOnce() -> T + Send + 'scope,
|
||||
T: Send + 'scope,
|
||||
{
|
||||
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(|| f(scope), Some(&scope.data)) }?))
|
||||
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(|| f(), Some(&scope.data)) }?))
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +247,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
|
||||
/// use std::thread;
|
||||
///
|
||||
/// thread::scope(|s| {
|
||||
/// let t = s.spawn(|_| {
|
||||
/// let t = s.spawn(|| {
|
||||
/// println!("hello");
|
||||
/// });
|
||||
/// println!("thread id: {:?}", t.thread().id());
|
||||
@ -279,7 +281,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
|
||||
/// use std::thread;
|
||||
///
|
||||
/// thread::scope(|s| {
|
||||
/// let t = s.spawn(|_| {
|
||||
/// let t = s.spawn(|| {
|
||||
/// panic!("oh no");
|
||||
/// });
|
||||
/// assert!(t.join().is_err());
|
||||
@ -299,7 +301,7 @@ impl<'scope, T> ScopedJoinHandle<'scope, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'env> fmt::Debug for Scope<'env> {
|
||||
impl<'scope, 'env> fmt::Debug for Scope<'scope, 'env> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Scope")
|
||||
.field("num_running_threads", &self.data.num_running_threads.load(Ordering::Relaxed))
|
||||
|
Loading…
Reference in New Issue
Block a user