Skip to content

Commit e7ed9a8

Browse files
committed
add more scope-spawn order tests
1 parent 8ccc028 commit e7ed9a8

File tree

1 file changed

+152
-38
lines changed

1 file changed

+152
-38
lines changed

rayon-core/src/scope/test.rs

Lines changed: 152 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -267,52 +267,166 @@ fn panic_propagate_still_execute_4() {
267267
}
268268
}
269269

270+
macro_rules! test_order {
271+
($scope:ident) => {{
272+
let builder = ThreadPoolBuilder::new().num_threads(1);
273+
let pool = builder.build().unwrap();
274+
pool.install(|| {
275+
let vec = Mutex::new(vec![]);
276+
$scope(|scope| {
277+
let vec = &vec;
278+
for i in 0..10 {
279+
scope.spawn(move |scope| {
280+
for j in 0..10 {
281+
scope.spawn(move |_| {
282+
vec.lock().unwrap().push(i * 10 + j);
283+
});
284+
}
285+
});
286+
}
287+
});
288+
vec.into_inner().unwrap()
289+
})
290+
}};
291+
}
292+
270293
#[test]
271294
fn lifo_order() {
272295
// In the absense of stealing, `scope()` runs its `spawn()` jobs in LIFO order.
273-
let builder = ThreadPoolBuilder::new().num_threads(1);
274-
let pool = builder.build().unwrap();
275-
pool.install(|| {
276-
let vec = Mutex::new(vec![]);
277-
scope(|scope| {
278-
let vec = &vec;
279-
for i in 0..10 {
280-
scope.spawn(move |scope| {
281-
for j in 0..10 {
282-
scope.spawn(move |_| {
283-
vec.lock().unwrap().push(i * 10 + j);
284-
});
285-
}
286-
});
287-
}
288-
});
289-
let vec = vec.into_inner().unwrap();
290-
let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed
291-
assert_eq!(vec, expected);
292-
});
296+
let vec = test_order!(scope);
297+
let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed
298+
assert_eq!(vec, expected);
293299
}
294300

295301
#[test]
296302
fn fifo_order() {
297303
// In the absense of stealing, `scope_fifo()` runs its `spawn()` jobs in FIFO order.
298-
let builder = ThreadPoolBuilder::new().num_threads(1);
299-
let pool = builder.build().unwrap();
300-
pool.install(|| {
301-
let vec = Mutex::new(vec![]);
302-
scope_fifo(|scope| {
303-
let vec = &vec;
304-
for i in 0..10 {
305-
scope.spawn(move |scope| {
306-
for j in 0..10 {
307-
scope.spawn(move |_| {
308-
vec.lock().unwrap().push(i * 10 + j);
304+
let vec = test_order!(scope_fifo);
305+
let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order
306+
assert_eq!(vec, expected);
307+
}
308+
309+
macro_rules! test_nested_order {
310+
($outer_scope:ident, $inner_scope:ident) => {{
311+
let builder = ThreadPoolBuilder::new().num_threads(1);
312+
let pool = builder.build().unwrap();
313+
pool.install(|| {
314+
let vec = Mutex::new(vec![]);
315+
$outer_scope(|scope| {
316+
let vec = &vec;
317+
for i in 0..10 {
318+
scope.spawn(move |_| {
319+
$inner_scope(|scope| {
320+
for j in 0..10 {
321+
scope.spawn(move |_| {
322+
vec.lock().unwrap().push(i * 10 + j);
323+
});
324+
}
309325
});
310-
}
326+
});
327+
}
328+
});
329+
vec.into_inner().unwrap()
330+
})
331+
}};
332+
}
333+
334+
#[test]
335+
fn nested_lifo_order() {
336+
// In the absense of stealing, `scope()` runs its `spawn()` jobs in LIFO order.
337+
let vec = test_nested_order!(scope, scope);
338+
let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed
339+
assert_eq!(vec, expected);
340+
}
341+
342+
#[test]
343+
fn nested_fifo_order() {
344+
// In the absense of stealing, `scope_fifo()` runs its `spawn()` jobs in FIFO order.
345+
let vec = test_nested_order!(scope_fifo, scope_fifo);
346+
let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order
347+
assert_eq!(vec, expected);
348+
}
349+
350+
#[test]
351+
fn nested_lifo_fifo_order() {
352+
// LIFO on the outside, FIFO on the inside
353+
let vec = test_nested_order!(scope, scope_fifo);
354+
let expected: Vec<i32> = (0..10)
355+
.rev()
356+
.flat_map(|i| (0..10).map(move |j| i * 10 + j))
357+
.collect();
358+
assert_eq!(vec, expected);
359+
}
360+
361+
#[test]
362+
fn nested_fifo_lifo_order() {
363+
// FIFO on the outside, LIFO on the inside
364+
let vec = test_nested_order!(scope_fifo, scope);
365+
let expected: Vec<i32> = (0..10)
366+
.flat_map(|i| (0..10).rev().map(move |j| i * 10 + j))
367+
.collect();
368+
assert_eq!(vec, expected);
369+
}
370+
371+
macro_rules! spawn_push {
372+
($scope:ident, $vec:ident, $i:expr) => {{
373+
$scope.spawn(move |_| $vec.lock().unwrap().push($i));
374+
}};
375+
}
376+
377+
/// Test spawns pushing a series of numbers, interleaved
378+
/// such that negative values are using an inner scope.
379+
macro_rules! test_mixed_order {
380+
($outer_scope:ident, $inner_scope:ident) => {{
381+
let builder = ThreadPoolBuilder::new().num_threads(1);
382+
let pool = builder.build().unwrap();
383+
pool.install(|| {
384+
let vec = Mutex::new(vec![]);
385+
$outer_scope(|outer_scope| {
386+
let vec = &vec;
387+
spawn_push!(outer_scope, vec, 0);
388+
$inner_scope(|inner_scope| {
389+
spawn_push!(inner_scope, vec, -1);
390+
spawn_push!(outer_scope, vec, 1);
391+
spawn_push!(inner_scope, vec, -2);
392+
spawn_push!(outer_scope, vec, 2);
393+
spawn_push!(inner_scope, vec, -3);
311394
});
312-
}
313-
});
314-
let vec = vec.into_inner().unwrap();
315-
let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order
316-
assert_eq!(vec, expected);
317-
});
395+
spawn_push!(outer_scope, vec, 3);
396+
});
397+
vec.into_inner().unwrap()
398+
})
399+
}};
400+
}
401+
402+
#[test]
403+
fn mixed_lifo_order() {
404+
// NB: the end of the inner scope makes us execute some of the outer scope
405+
// before they've all been spawned, so they're not perfectly LIFO.
406+
let vec = test_mixed_order!(scope, scope);
407+
let expected = vec![-3, 2, -2, 1, -1, 3, 0];
408+
assert_eq!(vec, expected);
409+
}
410+
411+
#[test]
412+
fn mixed_fifo_order() {
413+
let vec = test_mixed_order!(scope_fifo, scope_fifo);
414+
let expected = vec![-1, 0, -2, 1, -3, 2, 3];
415+
assert_eq!(vec, expected);
416+
}
417+
418+
#[test]
419+
fn mixed_lifo_fifo_order() {
420+
// NB: the end of the inner scope makes us execute some of the outer scope
421+
// before they've all been spawned, so they're not perfectly LIFO.
422+
let vec = test_mixed_order!(scope, scope_fifo);
423+
let expected = vec![-1, 2, -2, 1, -3, 3, 0];
424+
assert_eq!(vec, expected);
425+
}
426+
427+
#[test]
428+
fn mixed_fifo_lifo_order() {
429+
let vec = test_mixed_order!(scope_fifo, scope);
430+
let expected = vec![-3, 0, -2, 1, -1, 2, 3];
431+
assert_eq!(vec, expected);
318432
}

0 commit comments

Comments
 (0)