use super::spawn_in;
use crate::rayon::{ThreadPoolBuilder, registry::WorkerThread};
use std::sync::{Arc, mpsc::channel};
fn spawn<F>(func: F)
where
F: FnOnce() + Send + 'static,
{
let worker = unsafe { WorkerThread::current().as_ref() }.expect("must run on a worker");
let registry = Arc::clone(worker.registry());
unsafe { spawn_in(func, ®istry) }
}
#[test]
fn spawn_then_join_in_worker() {
let (tx, rx) = channel();
let pool = ThreadPoolBuilder::new().num_threads(4).build().unwrap();
pool.install(move || spawn(move || tx.send(22).unwrap()));
assert_eq!(22, rx.recv().unwrap());
}
#[test]
fn spawn_then_join_outside_worker() {
let (tx, rx) = channel();
let pool = ThreadPoolBuilder::new().num_threads(4).build().unwrap();
pool.spawn(move || tx.send(22).unwrap());
assert_eq!(22, rx.recv().unwrap());
}
#[test]
fn termination_while_things_are_executing() {
let (tx0, rx0) = channel();
let (tx1, rx1) = channel();
{
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
thread_pool.spawn(move || {
let data = rx0.recv().unwrap();
spawn(move || {
tx1.send(data).unwrap();
});
});
}
tx0.send(22).unwrap();
let v = rx1.recv().unwrap();
assert_eq!(v, 22);
}
macro_rules! test_order {
($outer_spawn:ident, $inner_spawn:ident) => {{
let builder = ThreadPoolBuilder::new().num_threads(1);
let pool = builder.build().unwrap();
let (tx, rx) = channel();
pool.install(move || {
for i in 0..10 {
let tx = tx.clone();
$outer_spawn(move || {
for j in 0..10 {
let tx = tx.clone();
$inner_spawn(move || {
tx.send(i * 10 + j).unwrap();
});
}
});
}
});
rx.iter().collect::<Vec<i32>>()
}};
}
#[test]
fn lifo_order() {
let vec = test_order!(spawn, spawn);
let expected: Vec<i32> = (0..100).rev().collect(); assert_eq!(vec, expected);
}