source: josm/trunk/test/unit/org/openstreetmap/josm/testutils/ParallelScheduler.java@ 17383

Last change on this file since 17383 was 14605, checked in by Don-vip, 5 years ago

see #16073 - convert single global test to one test per imagery entry

Slower, but this improves readbility and allows to focus on entries failing for several consecutive tries.

File size: 4.3 KB
Line 
1/**
2 * Copyright 2012-2017 Michael Tamm and other junit-toolbox contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.openstreetmap.josm.testutils;
17
18import static java.util.concurrent.ForkJoinTask.inForkJoinPool;
19
20import java.util.Deque;
21import java.util.LinkedList;
22import java.util.concurrent.ForkJoinPool;
23import java.util.concurrent.ForkJoinTask;
24import java.util.concurrent.ForkJoinWorkerThread;
25
26import org.junit.runners.model.RunnerScheduler;
27
28/**
29 * Encapsulates the singleton {@link ForkJoinPool} used by {@link ParallelParameterized}
30 * to execute test classes and test methods concurrently.
31 *
32 * @author Michael Tamm (junit-toolbox)
33 */
34class ParallelScheduler implements RunnerScheduler {
35
36 static ForkJoinPool forkJoinPool = setUpForkJoinPool();
37
38 static ForkJoinPool setUpForkJoinPool() {
39 Runtime runtime = Runtime.getRuntime();
40 int numThreads = Math.max(2, runtime.availableProcessors());
41 ForkJoinPool.ForkJoinWorkerThreadFactory threadFactory = pool -> {
42 if (pool.getPoolSize() >= pool.getParallelism()) {
43 return null;
44 } else {
45 ForkJoinWorkerThread thread = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
46 thread.setName("JUnit-" + thread.getName());
47 return thread;
48 }
49 };
50 return new ForkJoinPool(numThreads, threadFactory, null, false);
51 }
52
53 private final Deque<ForkJoinTask<?>> _asyncTasks = new LinkedList<>();
54 private Runnable _lastScheduledChild;
55
56 @Override
57 public void schedule(Runnable childStatement) {
58 if (_lastScheduledChild != null) {
59 // Execute previously scheduled child asynchronously ...
60 if (inForkJoinPool()) {
61 _asyncTasks.addFirst(ForkJoinTask.adapt(_lastScheduledChild).fork());
62 } else {
63 _asyncTasks.addFirst(forkJoinPool.submit(_lastScheduledChild));
64 }
65 }
66 // Note: We don't schedule the childStatement immediately here,
67 // but remember it, so that we can synchronously execute the
68 // last scheduled child in the finished method() -- this way,
69 // the current thread does not immediately call join() in the
70 // finished() method, which might block it ...
71 _lastScheduledChild = childStatement;
72 }
73
74 @Override
75 public void finished() {
76 RuntimeException me = new RuntimeException();
77 if (_lastScheduledChild != null) {
78 if (inForkJoinPool()) {
79 // Execute the last scheduled child in the current thread ...
80 try {
81 _lastScheduledChild.run();
82 } catch (Throwable t) {
83 me.addSuppressed(t);
84 }
85 } else {
86 // Submit the last scheduled child to the ForkJoinPool too,
87 // because all tests should run in the worker threads ...
88 _asyncTasks.addFirst(forkJoinPool.submit(_lastScheduledChild));
89 }
90 // Make sure all asynchronously executed children are done, before we return ...
91 for (ForkJoinTask<?> task : _asyncTasks) {
92 // Note: Because we have added all tasks via addFirst into _asyncTasks,
93 // task.join() is able to steal tasks from other worker threads,
94 // if there are tasks, which have not been started yet ...
95 // from other worker threads ...
96 try {
97 task.join();
98 } catch (Throwable t) {
99 me.addSuppressed(t);
100 }
101 }
102 if (me.getSuppressed().length > 0) {
103 throw me;
104 }
105 }
106 }
107}
Note: See TracBrowser for help on using the repository browser.