Ticket #17819: 17819-multi-thread.patch
File 17819-multi-thread.patch, 5.5 KB (added by , 5 years ago) |
---|
-
src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java
16 16 import java.util.Map; 17 17 import java.util.Map.Entry; 18 18 import java.util.Set; 19 import java.util.concurrent.ForkJoinPool; 20 import java.util.concurrent.ForkJoinTask; 21 import java.util.concurrent.RecursiveTask; 19 22 20 23 import org.openstreetmap.josm.command.ChangeCommand; 21 24 import org.openstreetmap.josm.command.Command; … … 38 41 import org.openstreetmap.josm.tools.Geometry; 39 42 import org.openstreetmap.josm.tools.Geometry.PolygonIntersection; 40 43 import org.openstreetmap.josm.tools.Logging; 44 import org.openstreetmap.josm.tools.Utils; 41 45 42 46 /** 43 47 * Checks if multipolygons are valid … … 44 48 * @since 3669 45 49 */ 46 50 public class MultipolygonTest extends Test { 51 private static final ForkJoinPool THREAD_POOL = newForkJoinPool(); 47 52 53 private static ForkJoinPool newForkJoinPool() { 54 try { 55 return Utils.newForkJoinPool( 56 "multipolygon_creation.numberOfThreads", "multipolygon-test-%d", Thread.NORM_PRIORITY); 57 } catch (SecurityException e) { 58 Logging.log(Logging.LEVEL_ERROR, "Unable to create new ForkJoinPool", e); 59 return null; 60 } 61 } 62 48 63 /** Non-Way in multipolygon */ 49 64 public static final int WRONG_MEMBER_TYPE = 1601; 50 65 /** No useful role for multipolygon member */ … … 461 476 * @param sharedNodes all nodes shared by multiple ways of this multipolygon 462 477 */ 463 478 private void checkRoles(Relation r, List<PolyData> allPolygons, Map<Long, RelationMember> wayMap, Set<Node> sharedNodes) { 464 PolygonLevelFinder levelFinder = new PolygonLevelFinder(sharedNodes); 465 List<PolygonLevel> list = levelFinder.findOuterWays(allPolygons); 479 List<PolygonLevel> list = findOuterWaysMultiThread(allPolygons, sharedNodes); 466 480 if (list == null || list.isEmpty()) { 467 481 return; 468 482 } … … 796 810 } 797 811 798 812 /** 813 * Collects outer way and corresponding inner ways from all rings. 814 * @param rings the polygon rings 815 * @param sharedNodes all nodes shared by multiple ways of this multipolygon 816 * @return list of nesting levels 817 */ 818 private static List<PolygonLevel> findOuterWaysMultiThread(List<PolyData> rings, Set<Node> sharedNodes) { 819 PolygonLevelFinder worker = new PolygonLevelFinder(sharedNodes, rings, 0, rings.size(), 820 new ArrayList<PolygonLevel>(), 128); 821 if (THREAD_POOL != null) { 822 return THREAD_POOL.invoke(worker); 823 } else { 824 return worker.computeDirectly(); 825 } 826 } 827 828 /** 799 829 * Find nesting levels of polygons. Logic taken from class MultipolygonBuilder, uses different structures. 800 830 */ 801 private static class PolygonLevelFinder { 802 private final Set<Node> sharedNodes; 831 private static class PolygonLevelFinder extends RecursiveTask<List<PolygonLevel>> { 832 private final transient Set<Node> sharedNodes; 833 private final transient List<PolyData> input; 834 private final int from; 835 private final int to; 836 private final transient List<PolygonLevel> output; 837 private final int directExecutionTaskSize; 803 838 804 PolygonLevelFinder(Set<Node> sharedNodes) { 839 private static final long serialVersionUID = 0; 840 841 PolygonLevelFinder(Set<Node> sharedNodes, List<PolyData> input, int from, int to, List<PolygonLevel> output, 842 int directExecutionTaskSize) { 805 843 this.sharedNodes = sharedNodes; 844 this.input = input; 845 this.from = from; 846 this.to = to; 847 this.output = output; 848 this.directExecutionTaskSize = directExecutionTaskSize; 806 849 } 807 850 808 List<PolygonLevel> findOuterWays(List<PolyData> allPolygons) {809 return findOuterWaysRecursive(0, allPolygons);810 }811 812 851 private List<PolygonLevel> findOuterWaysRecursive(int level, List<PolyData> polygons) { 813 852 final List<PolygonLevel> result = new ArrayList<>(); 814 853 … … 906 945 } 907 946 return null; 908 947 } 948 949 @Override 950 protected List<PolygonLevel> compute() { 951 if (to - from <= directExecutionTaskSize) { 952 return computeDirectly(); 953 } else { 954 final Collection<ForkJoinTask<List<PolygonLevel>>> tasks = new ArrayList<>(); 955 for (int fromIndex = from; fromIndex < to; fromIndex += directExecutionTaskSize) { 956 tasks.add(new PolygonLevelFinder(sharedNodes, input, fromIndex, Math.min(fromIndex + directExecutionTaskSize, to), 957 new ArrayList<PolygonLevel>(), directExecutionTaskSize)); 958 } 959 for (ForkJoinTask<List<PolygonLevel>> task : ForkJoinTask.invokeAll(tasks)) { 960 List<PolygonLevel> res = task.join(); 961 if (res == null) { 962 return null; 963 } 964 output.addAll(res); 965 } 966 return output; 967 } 968 } 969 970 List<PolygonLevel> computeDirectly() { 971 for (int i = from; i < to; i++) { 972 processOuterWay(0, input, output, input.get(i)); 973 } 974 return output; 975 } 909 976 } 910 977 911 978 /**