1414import static java .util .Objects .requireNonNull ;
1515import static java .util .concurrent .CompletableFuture .completedFuture ;
1616import static java .util .concurrent .TimeUnit .SECONDS ;
17- import static java .util .function .Predicate .isEqual ;
1817import static org .apiguardian .api .API .Status .EXPERIMENTAL ;
1918import static org .junit .platform .commons .util .ExceptionUtils .throwAsUncheckedException ;
2019import static org .junit .platform .engine .support .hierarchical .ExclusiveResource .GLOBAL_READ_WRITE ;
4645import java .util .function .BiFunction ;
4746import java .util .function .BooleanSupplier ;
4847import java .util .function .Consumer ;
49- import java .util .function .Predicate ;
5048
5149import org .apiguardian .api .API ;
5250import org .jspecify .annotations .Nullable ;
@@ -294,15 +292,29 @@ void processQueueEntries(WorkerLease workerLease, BooleanSupplier doneCondition)
294292 }
295293
296294 private void processQueueEntries () {
297- var queueEntriesByResult = tryToStealWorkWithoutBlocking (workQueue ,
298- isEqual (WorkStealResult .EXECUTED_BY_THIS_WORKER ));
299- var queueModified = queueEntriesByResult .containsKey (WorkStealResult .EXECUTED_BY_THIS_WORKER ) //
300- || queueEntriesByResult .containsKey (WorkStealResult .EXECUTED_BY_DIFFERENT_WORKER );
295+ var entriesRequiringResourceLocks = new ArrayList <WorkQueue .Entry >();
296+ var queueModified = false ;
297+
298+ for (var entry : workQueue ) {
299+ var result = tryToStealWork (entry , BlockingMode .NON_BLOCKING );
300+ // After executing a test a significant amount of time has passed.
301+ // Process the queue from the beginning
302+ if (result == WorkStealResult .EXECUTED_BY_THIS_WORKER ) {
303+ return ;
304+ }
305+ if (result == WorkStealResult .EXECUTED_BY_DIFFERENT_WORKER ) {
306+ queueModified = true ;
307+ }
308+ if (result == WorkStealResult .RESOURCE_LOCK_UNAVAILABLE ) {
309+ entriesRequiringResourceLocks .add (entry );
310+ }
311+ }
312+ // The queue changed while we looked at it.
313+ // Check from the start before processing any blocked items.
301314 if (queueModified ) {
302315 return ;
303316 }
304- var entriesRequiringResourceLocks = queueEntriesByResult .get (WorkStealResult .RESOURCE_LOCK_UNAVAILABLE );
305- if (entriesRequiringResourceLocks != null ) {
317+ if (!entriesRequiringResourceLocks .isEmpty ()) {
306318 // One entry at a time to avoid blocking too much
307319 tryToStealWork (entriesRequiringResourceLocks .get (0 ), BlockingMode .BLOCKING );
308320 }
@@ -339,7 +351,7 @@ void invokeAll(List<? extends TestTask> testTasks) {
339351 List <TestTask > sameThreadTasks = new ArrayList <>(testTasks .size ());
340352 var queueEntries = forkConcurrentChildren (testTasks , isolatedTasks ::add , sameThreadTasks );
341353 executeAll (sameThreadTasks );
342- var queueEntriesByResult = tryToStealWorkWithoutBlocking (queueEntries , __ -> false );
354+ var queueEntriesByResult = tryToStealWorkWithoutBlocking (queueEntries );
343355 tryToStealWorkWithBlocking (queueEntriesByResult );
344356 waitFor (queueEntriesByResult );
345357 executeAll (isolatedTasks );
@@ -374,10 +386,10 @@ else if (child.getExecutionMode() == SAME_THREAD) {
374386 }
375387
376388 private Map <WorkStealResult , List <WorkQueue .Entry >> tryToStealWorkWithoutBlocking (
377- Iterable <WorkQueue .Entry > queueEntries , Predicate <? super WorkStealResult > stopCondition ) {
389+ Iterable <WorkQueue .Entry > queueEntries ) {
378390
379391 Map <WorkStealResult , List <WorkQueue .Entry >> queueEntriesByResult = new EnumMap <>(WorkStealResult .class );
380- tryToStealWork (queueEntries , BlockingMode .NON_BLOCKING , queueEntriesByResult , stopCondition );
392+ tryToStealWork (queueEntries , BlockingMode .NON_BLOCKING , queueEntriesByResult );
381393 return queueEntriesByResult ;
382394 }
383395
@@ -386,18 +398,14 @@ private void tryToStealWorkWithBlocking(Map<WorkStealResult, List<WorkQueue.Entr
386398 if (entriesRequiringResourceLocks == null ) {
387399 return ;
388400 }
389- tryToStealWork (entriesRequiringResourceLocks , BlockingMode .BLOCKING , queueEntriesByResult , __ -> false );
401+ tryToStealWork (entriesRequiringResourceLocks , BlockingMode .BLOCKING , queueEntriesByResult );
390402 }
391403
392404 private void tryToStealWork (Iterable <WorkQueue .Entry > entries , BlockingMode blocking ,
393- Map <WorkStealResult , List <WorkQueue .Entry >> queueEntriesByResult ,
394- Predicate <? super WorkStealResult > stopCondition ) {
405+ Map <WorkStealResult , List <WorkQueue .Entry >> queueEntriesByResult ) {
395406 for (var entry : entries ) {
396407 var result = tryToStealWork (entry , blocking );
397408 queueEntriesByResult .computeIfAbsent (result , __ -> new ArrayList <>()).add (entry );
398- if (stopCondition .test (result )) {
399- break ;
400- }
401409 }
402410 }
403411
0 commit comments