Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1063: core: Introduce ThreadPoolBuilder::use_current_thread. r=cuviper a=emilio This generalizes the approach used by targets that don't support threading like wasm, allowing the builder thread to be part of a new thread-pool. This PR: * Builds on top of the PoC implementation from that issue. * Renames the API as per the comments there. * Adds a way to clean up the WorkerThread storage once the pool is dropped. * Documents and tests the APIs. Feedback welcome. `clean_up_use_current_thread` is not a great name, but I think it's descriptive, and maybe good enough given it's a rather niche API for non-global pools? Co-authored-by: Josh Stone <cuviper@gmail.com> Co-authored-by: Emilio Cobos Álvarez <emilio@crisal.io>
- Loading branch information
Showing
4 changed files
with
113 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use rayon_core::ThreadPoolBuilder; | ||
use std::sync::{Arc, Condvar, Mutex}; | ||
use std::thread::{self, JoinHandle}; | ||
|
||
#[test] | ||
#[cfg_attr(any(target_os = "emscripten", target_family = "wasm"), ignore)] | ||
fn use_current_thread_basic() { | ||
static JOIN_HANDLES: Mutex<Vec<JoinHandle<()>>> = Mutex::new(Vec::new()); | ||
let pool = ThreadPoolBuilder::new() | ||
.num_threads(2) | ||
.use_current_thread() | ||
.spawn_handler(|builder| { | ||
let handle = thread::Builder::new().spawn(|| builder.run())?; | ||
JOIN_HANDLES.lock().unwrap().push(handle); | ||
Ok(()) | ||
}) | ||
.build() | ||
.unwrap(); | ||
assert_eq!(rayon_core::current_thread_index(), Some(0)); | ||
assert_eq!( | ||
JOIN_HANDLES.lock().unwrap().len(), | ||
1, | ||
"Should only spawn one extra thread" | ||
); | ||
|
||
let another_pool = ThreadPoolBuilder::new() | ||
.num_threads(2) | ||
.use_current_thread() | ||
.build(); | ||
assert!( | ||
another_pool.is_err(), | ||
"Should error if the thread is already part of a pool" | ||
); | ||
|
||
let pair = Arc::new((Mutex::new(false), Condvar::new())); | ||
let pair2 = Arc::clone(&pair); | ||
pool.spawn(move || { | ||
assert_ne!(rayon_core::current_thread_index(), Some(0)); | ||
// This should execute even if the current thread is blocked, since we have two threads in | ||
// the pool. | ||
let &(ref started, ref condvar) = &*pair2; | ||
*started.lock().unwrap() = true; | ||
condvar.notify_one(); | ||
}); | ||
|
||
let _guard = pair | ||
.1 | ||
.wait_while(pair.0.lock().unwrap(), |ran| !*ran) | ||
.unwrap(); | ||
std::mem::drop(pool); // Drop the pool. | ||
|
||
// Wait until all threads have actually exited. This is not really needed, other than to | ||
// reduce noise of leak-checking tools. | ||
for handle in std::mem::take(&mut *JOIN_HANDLES.lock().unwrap()) { | ||
let _ = handle.join(); | ||
} | ||
} |