@@ -267,52 +267,166 @@ fn panic_propagate_still_execute_4() {
267
267
}
268
268
}
269
269
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
+
270
293
#[ test]
271
294
fn lifo_order ( ) {
272
295
// 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) ;
293
299
}
294
300
295
301
#[ test]
296
302
fn fifo_order ( ) {
297
303
// 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
+ }
309
325
} ) ;
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 ) ;
311
394
} ) ;
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) ;
318
432
}
0 commit comments