Ticket #18534: 18534.synchronizedMap.patch
| File 18534.synchronizedMap.patch, 9.3 KB (added by , 6 years ago) |
|---|
-
src/org/openstreetmap/josm/tools/ImageProvider.java
34 34 import java.util.Arrays; 35 35 import java.util.Base64; 36 36 import java.util.Collection; 37 import java.util.Collections; 37 38 import java.util.EnumMap; 38 39 import java.util.HashMap; 39 40 import java.util.Hashtable; … … 295 296 /** 296 297 * The icon cache 297 298 */ 298 private static final Map<String, ImageResource> cache = new HashMap<>();299 private static final Map<String, ImageResource> cache = Collections.synchronizedMap(new HashMap<>()); 299 300 300 301 /** 301 302 * Caches the image data for rotated versions of the same image. … … 835 836 * @since 11021 836 837 */ 837 838 public static void clearCache() { 838 synchronized (cache) { 839 cache.clear(); 840 } 839 cache.clear(); 841 840 synchronized (ROTATE_CACHE) { 842 841 ROTATE_CACHE.clear(); 843 842 } … … 855 854 * @return the requested image or null if the request failed 856 855 */ 857 856 private ImageResource getIfAvailableImpl() { 858 synchronized (cache) {859 // This method is called from different thread and modifying HashMap concurrently can result860 // for example in loops in map entries (ie freeze whensuch entry is retrieved)857 // This method is called from different thread and modifying HashMap 858 // concurrently can result for example in loops in map entries (ie freeze when 859 // such entry is retrieved) 861 860 862 String prefix = isDisabled ? "dis:" : ""; 863 if (name.startsWith("data:")) { 864 String url = name; 865 ImageResource ir = cache.get(prefix+url); 866 if (ir != null) return ir; 867 ir = getIfAvailableDataUrl(url); 868 if (ir != null) { 869 cache.put(prefix+url, ir); 870 } 861 String prefix = isDisabled ? "dis:" : ""; 862 if (name.startsWith("data:")) { 863 String url = name; 864 ImageResource ir = cache.get(prefix + url); 865 if (ir != null) 871 866 return ir; 867 ir = getIfAvailableDataUrl(url); 868 if (ir != null) { 869 cache.put(prefix + url, ir); 872 870 } 871 return ir; 872 } 873 873 874 ImageType type = Utils.hasExtension(name, "svg") ? ImageType.SVG : ImageType.OTHER;874 ImageType type = Utils.hasExtension(name, "svg") ? ImageType.SVG : ImageType.OTHER; 875 875 876 if (name.startsWith(HTTP_PROTOCOL) || name.startsWith(HTTPS_PROTOCOL)) { 877 String url = name; 878 ImageResource ir = cache.get(prefix+url); 879 if (ir != null) return ir; 880 ir = getIfAvailableHttp(url, type); 881 if (ir != null) { 882 cache.put(prefix+url, ir); 883 } 876 if (name.startsWith(HTTP_PROTOCOL) || name.startsWith(HTTPS_PROTOCOL)) { 877 String url = name; 878 ImageResource ir = cache.get(prefix + url); 879 if (ir != null) 884 880 return ir; 885 } else if (name.startsWith(WIKI_PROTOCOL)) { 886 ImageResource ir = cache.get(prefix+name); 887 if (ir != null) return ir; 888 ir = getIfAvailableWiki(name, type); 889 if (ir != null) { 890 cache.put(prefix+name, ir); 891 } 881 ir = getIfAvailableHttp(url, type); 882 if (ir != null) { 883 cache.put(prefix + url, ir); 884 } 885 return ir; 886 } else if (name.startsWith(WIKI_PROTOCOL)) { 887 ImageResource ir = cache.get(prefix + name); 888 if (ir != null) 892 889 return ir; 890 ir = getIfAvailableWiki(name, type); 891 if (ir != null) { 892 cache.put(prefix + name, ir); 893 893 } 894 return ir; 895 } 894 896 895 if (subdir == null) {896 subdir = "";897 } else if (!subdir.isEmpty() && !subdir.endsWith("/")) {898 subdir += '/';899 }900 String[] extensions;901 if (name.indexOf('.') != -1) {902 extensions = new String[] {""};903 } else {904 extensions = new String[] {".png", ".svg"};905 }906 final int typeArchive = 0;907 final int typeLocal = 1;908 for (int place : new Integer[] {typeArchive, typeLocal}) {909 for (String ext : extensions) {897 if (subdir == null) { 898 subdir = ""; 899 } else if (!subdir.isEmpty() && !subdir.endsWith("/")) { 900 subdir += '/'; 901 } 902 String[] extensions; 903 if (name.indexOf('.') != -1) { 904 extensions = new String[] { "" }; 905 } else { 906 extensions = new String[] { ".png", ".svg" }; 907 } 908 final int typeArchive = 0; 909 final int typeLocal = 1; 910 for (int place : new Integer[] { typeArchive, typeLocal }) { 911 for (String ext : extensions) { 910 912 911 if (".svg".equals(ext)) {912 type = ImageType.SVG;913 } else if (".png".equals(ext)) {914 type = ImageType.OTHER;915 }913 if (".svg".equals(ext)) { 914 type = ImageType.SVG; 915 } else if (".png".equals(ext)) { 916 type = ImageType.OTHER; 917 } 916 918 917 String fullName = subdir + name + ext; 918 String cacheName = prefix + fullName; 919 /* cache separately */ 920 if (dirs != null && !dirs.isEmpty()) { 921 cacheName = "id:" + id + ':' + fullName; 922 if (archive != null) { 923 cacheName += ':' + archive.getName(); 924 } 919 String fullName = subdir + name + ext; 920 String cacheName = prefix + fullName; 921 /* cache separately */ 922 if (dirs != null && !dirs.isEmpty()) { 923 cacheName = "id:" + id + ':' + fullName; 924 if (archive != null) { 925 cacheName += ':' + archive.getName(); 925 926 } 927 } 926 928 927 switch (place) { 928 case typeArchive: 929 if (archive != null) { 930 cacheName = "zip:"+archive.hashCode()+':'+cacheName; 931 ImageResource ir = cache.get(cacheName); 932 if (ir != null) return ir; 933 934 ir = getIfAvailableZip(fullName, archive, inArchiveDir, type); 935 if (ir != null) { 936 cache.put(cacheName, ir); 937 return ir; 938 } 939 } 940 break; 941 case typeLocal: 929 switch (place) { 930 case typeArchive: 931 if (archive != null) { 932 cacheName = "zip:" + archive.hashCode() + ':' + cacheName; 942 933 ImageResource ir = cache.get(cacheName); 943 934 if (ir != null) return ir; 944 935 945 // getImageUrl() does a ton of "stat()" calls and gets expensive 946 // and redundant when you have a whole ton of objects. So, 947 // index the cache by the name of the icon we're looking for 948 // and don't bother to create a URL unless we're actually creating the image. 949 URL path = getImageUrl(fullName); 950 if (path == null) { 951 continue; 952 } 953 ir = getIfAvailableLocalURL(path, type); 936 ir = getIfAvailableZip(fullName, archive, inArchiveDir, type); 954 937 if (ir != null) { 955 938 cache.put(cacheName, ir); 956 939 return ir; 957 940 } 958 break;959 941 } 942 break; 943 case typeLocal: 944 ImageResource ir = cache.get(cacheName); 945 if (ir != null) 946 return ir; 947 948 // getImageUrl() does a ton of "stat()" calls and gets expensive 949 // and redundant when you have a whole ton of objects. So, 950 // index the cache by the name of the icon we're looking for 951 // and don't bother to create a URL unless we're actually creating the image. 952 URL path = getImageUrl(fullName); 953 if (path == null) { 954 continue; 955 } 956 ir = getIfAvailableLocalURL(path, type); 957 if (ir != null) { 958 cache.put(cacheName, ir); 959 return ir; 960 } 961 break; 960 962 } 961 963 } 962 return null;963 964 } 965 return null; 964 966 } 965 967 966 968 /**
