Skip to content

Commit 09f58e3

Browse files
committed
Add ThreadPoolBuilder::build_scoped()
1 parent af3fb74 commit 09f58e3

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

rayon-core/src/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,32 @@ impl ThreadPoolBuilder {
186186
thread_pool::build(self)
187187
}
188188

189+
/// Create a scoped `ThreadPool` initialized using this configuration.
190+
///
191+
/// The threads in this pool will start by calling `wrapper`, which should
192+
/// do initialization and continue by calling `ThreadBuilder::run()`.
193+
pub fn build_scoped<W, F, R>(self, wrapper: W, with_pool: F) -> Result<R, ThreadPoolBuildError>
194+
where
195+
W: Fn(ThreadBuilder) + Sync, // expected to call `run()`
196+
F: FnOnce(&ThreadPool) -> R,
197+
{
198+
crossbeam::scope(|scope| {
199+
let wrapper = &wrapper;
200+
let pool = self.spawn(|thread| {
201+
let mut builder = scope.builder();
202+
if let Some(name) = thread.name() {
203+
builder = builder.name(name.to_string());
204+
}
205+
if let Some(size) = thread.stack_size() {
206+
builder = builder.stack_size(size);
207+
}
208+
builder.spawn(move || wrapper(thread))?;
209+
Ok(())
210+
})?;
211+
Ok(with_pool(&pool))
212+
})
213+
}
214+
189215
/// Create a new `ThreadPool` initialized using this configuration and a
190216
/// custom function for spawning threads.
191217
///

rayon-core/tests/scoped_threadpool.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Local(i32);
1212
scoped_thread_local!(static LOCAL: Local);
1313

1414
#[test]
15-
fn scoped_tls_missing() {
15+
fn missing_scoped_tls() {
1616
LOCAL.set(&Local(42), || {
1717
let pool = ThreadPoolBuilder::new()
1818
.build()
@@ -26,7 +26,7 @@ fn scoped_tls_missing() {
2626
}
2727

2828
#[test]
29-
fn scoped_tls_threadpool() {
29+
fn spawn_scoped_tls_threadpool() {
3030
LOCAL.set(&Local(42), || {
3131
LOCAL.with(|x| {
3232
crossbeam::scope(|scope| {
@@ -64,3 +64,36 @@ fn scoped_tls_threadpool() {
6464
});
6565
});
6666
}
67+
68+
#[test]
69+
fn build_scoped_tls_threadpool() {
70+
LOCAL.set(&Local(42), || {
71+
LOCAL.with(|x| {
72+
ThreadPoolBuilder::new()
73+
.build_scoped(
74+
move |thread| LOCAL.set(x, || thread.run()),
75+
|pool| {
76+
// The pool matches our local value.
77+
pool.install(|| {
78+
assert!(LOCAL.is_set());
79+
LOCAL.with(|y| {
80+
assert_eq!(x, y);
81+
});
82+
});
83+
84+
// If we change our local value, the pool is not affected.
85+
LOCAL.set(&Local(-1), || {
86+
pool.install(|| {
87+
assert!(LOCAL.is_set());
88+
LOCAL.with(|y| {
89+
assert_eq!(x, y);
90+
});
91+
});
92+
});
93+
},
94+
)
95+
.expect("thread pool created");
96+
// Internally, `crossbeam::scope` will wait for the threads to exit before returning.
97+
});
98+
});
99+
}

0 commit comments

Comments
 (0)