19
19
import java .net .URISyntaxException ;
20
20
import java .util .ArrayList ;
21
21
import java .util .Arrays ;
22
- import java .util .Collections ;
23
22
import java .util .HashMap ;
24
23
import java .util .HashSet ;
25
24
import java .util .LinkedHashSet ;
26
25
import java .util .List ;
27
26
import java .util .Map ;
28
27
import java .util .Set ;
28
+ import java .util .concurrent .locks .ReentrantReadWriteLock ;
29
+ import java .util .function .Function ;
29
30
import java .util .regex .Matcher ;
30
31
import java .util .regex .Pattern ;
31
32
@@ -95,12 +96,16 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
95
96
96
97
private static final int FIND_RESOURCES_CACHE_SIZE = 100 ;
97
98
98
- private Map <URI , IResource []> workspaceRootFindContainersForLocationURICache = Collections
99
- .synchronizedMap (new LRUCache <>(FIND_RESOURCES_CACHE_SIZE ));
100
- private Map <URI , IResource []> workspaceRootFindFilesForLocationURICache = Collections
101
- .synchronizedMap (new LRUCache <>(FIND_RESOURCES_CACHE_SIZE ));
102
- private Map <IProject , LRUCache <IPath , List <IResource >>> findPathInProjectCache = Collections
103
- .synchronizedMap (new HashMap <>());
99
+ private LRUCache <URI , IResource []> workspaceRootFindContainersForLocationURICache = new LRUCache <>(
100
+ FIND_RESOURCES_CACHE_SIZE );
101
+ private LRUCache <URI , IResource []> workspaceRootFindFilesForLocationURICache = new LRUCache <>(
102
+ FIND_RESOURCES_CACHE_SIZE );
103
+ private HashMap <IProject , LRUCache <IPath , List <IResource >>> findPathInProjectCache = new HashMap <>();
104
+
105
+ private final ReentrantReadWriteLock findContainersForLocationURICacheLock = new ReentrantReadWriteLock ();
106
+ private final ReentrantReadWriteLock findFilesForLocationURICacheLock = new ReentrantReadWriteLock ();
107
+ private final ReentrantReadWriteLock findPathInProjectCacheLock = new ReentrantReadWriteLock ();
108
+ private final ReentrantReadWriteLock findPathInFoldertCacheLock = new ReentrantReadWriteLock ();
104
109
105
110
//String pathStr, URI baseURI -> URI
106
111
private static class MappedURIKey {
@@ -146,14 +151,14 @@ public boolean equals(Object obj) {
146
151
}
147
152
148
153
// Caches the result of determineMappedURI
149
- private Map <MappedURIKey , URI > mappedURICache = Collections
150
- .synchronizedMap (new LRUCache <>(FIND_RESOURCES_CACHE_SIZE ));
154
+ private LRUCache <MappedURIKey , URI > mappedURICache = new LRUCache <>(FIND_RESOURCES_CACHE_SIZE );
151
155
// Caches the result of getFilesystemLocation
152
- private Map <URI , IPath > fileSystemLocationCache = Collections
153
- .synchronizedMap (new LRUCache <>(FIND_RESOURCES_CACHE_SIZE ));
156
+ private LRUCache <URI , IPath > fileSystemLocationCache = new LRUCache <>(FIND_RESOURCES_CACHE_SIZE );
154
157
// Caches the result of new File(pathname).exists()
155
- private Map <IPath , Boolean > pathExistsCache = Collections
156
- .synchronizedMap (new LRUCache <>(FIND_RESOURCES_CACHE_SIZE ));
158
+ private LRUCache <IPath , Boolean > pathExistsCache = new LRUCache <>(FIND_RESOURCES_CACHE_SIZE );
159
+ private final ReentrantReadWriteLock mappedURICacheLock = new ReentrantReadWriteLock ();
160
+ private final ReentrantReadWriteLock fileSystemLocationCacheLock = new ReentrantReadWriteLock ();
161
+ private final ReentrantReadWriteLock pathExistsCacheLock = new ReentrantReadWriteLock ();
157
162
158
163
/** @since 8.2 */
159
164
protected EFSExtensionProvider efsProvider = null ;
@@ -797,8 +802,9 @@ private IResource findFileForLocationURI(URI uri, IProject preferredProject, boo
797
802
}
798
803
IResource sourceFile = null ;
799
804
800
- IResource [] resources = workspaceRootFindFilesForLocationURICache .computeIfAbsent (uri ,
801
- key -> ResourcesPlugin .getWorkspace ().getRoot ().findFilesForLocationURI (key ));
805
+ IResource [] resources = threadSafeComputeIfAbsent (uri , workspaceRootFindFilesForLocationURICache ,
806
+ key -> ResourcesPlugin .getWorkspace ().getRoot ().findFilesForLocationURI (key ),
807
+ findFilesForLocationURICacheLock );
802
808
for (IResource rc : resources ) {
803
809
if (!checkExistence || rc .isAccessible ()) {
804
810
if (rc .getProject ().equals (preferredProject )) {
@@ -820,8 +826,9 @@ private IResource findFileForLocationURI(URI uri, IProject preferredProject, boo
820
826
private IResource findContainerForLocationURI (URI uri , IProject preferredProject , boolean checkExistence ) {
821
827
IResource resource = null ;
822
828
823
- IResource [] resources = workspaceRootFindContainersForLocationURICache .computeIfAbsent (uri ,
824
- key -> ResourcesPlugin .getWorkspace ().getRoot ().findContainersForLocationURI (key ));
829
+ IResource [] resources = threadSafeComputeIfAbsent (uri , workspaceRootFindContainersForLocationURICache ,
830
+ (key ) -> ResourcesPlugin .getWorkspace ().getRoot ().findContainersForLocationURI (key ),
831
+ findContainersForLocationURICacheLock );
825
832
for (IResource rc : resources ) {
826
833
if ((rc instanceof IProject || rc instanceof IFolder ) && (!checkExistence || rc .isAccessible ())) { // treat IWorkspaceRoot as non-workspace path
827
834
if (rc .getProject ().equals (preferredProject )) {
@@ -1016,7 +1023,7 @@ private static URI resolvePathFromBaseLocation(String pathStr0, IPath baseLocati
1016
1023
* @return {@link URI} of the resource
1017
1024
*/
1018
1025
private URI determineMappedURI (String pathStr , URI baseURI ) {
1019
- return mappedURICache . computeIfAbsent (new MappedURIKey (baseURI , pathStr ), key -> {
1026
+ return threadSafeComputeIfAbsent (new MappedURIKey (baseURI , pathStr ), mappedURICache , key -> {
1020
1027
URI uri = null ;
1021
1028
1022
1029
if (baseURI == null ) {
@@ -1045,16 +1052,16 @@ private URI determineMappedURI(String pathStr, URI baseURI) {
1045
1052
uri = org .eclipse .core .filesystem .URIUtil .toURI (pathStr );
1046
1053
}
1047
1054
return uri ;
1048
- });
1055
+ }, mappedURICacheLock );
1049
1056
}
1050
1057
1051
1058
/**
1052
1059
* Find all resources in the project which might be represented by relative path passed.
1053
1060
*/
1054
1061
private List <IResource > findPathInProject (IPath path , IProject project ) {
1055
- LRUCache <IPath , List <IResource >> cache = findPathInProjectCache . computeIfAbsent (project ,
1056
- key -> new LRUCache <> (FIND_RESOURCES_CACHE_SIZE ));
1057
- return cache . computeIfAbsent (path , key -> findPathInFolder (path , project ));
1062
+ LRUCache <IPath , List <IResource >> cache = threadSafeComputeIfAbsent (project , findPathInProjectCache ,
1063
+ key -> new LRUCache <IPath , List < IResource >> (FIND_RESOURCES_CACHE_SIZE ), findPathInProjectCacheLock );
1064
+ return threadSafeComputeIfAbsent (path , cache , key -> findPathInFolder (path , project ), findPathInFoldertCacheLock );
1058
1065
}
1059
1066
1060
1067
/**
@@ -1162,8 +1169,7 @@ private IResource findBestFitInWorkspace(String parsedName) {
1162
1169
private IPath getFilesystemLocation (URI uri ) {
1163
1170
if (uri == null )
1164
1171
return null ;
1165
-
1166
- return fileSystemLocationCache .computeIfAbsent (uri , (k ) -> {
1172
+ return threadSafeComputeIfAbsent (uri , fileSystemLocationCache , (k ) -> {
1167
1173
String pathStr = efsProvider .getMappedPath (uri );
1168
1174
URI resUri = org .eclipse .core .filesystem .URIUtil .toURI (pathStr );
1169
1175
@@ -1180,7 +1186,7 @@ private IPath getFilesystemLocation(URI uri) {
1180
1186
}
1181
1187
}
1182
1188
return null ;
1183
- });
1189
+ }, fileSystemLocationCacheLock );
1184
1190
}
1185
1191
1186
1192
/**
@@ -1261,9 +1267,9 @@ private ICLanguageSettingEntry resolvePathEntryInFilesystem(AbstractOptionParser
1261
1267
IPath location = getFilesystemLocation (uri );
1262
1268
if (location != null ) {
1263
1269
String loc = location .toString ();
1264
- boolean exists = pathExistsCache . computeIfAbsent (location , (s ) -> {
1270
+ boolean exists = threadSafeComputeIfAbsent (location , pathExistsCache , (s ) -> {
1265
1271
return new File (loc ).exists ();
1266
- });
1272
+ }, pathExistsCacheLock );
1267
1273
if (exists ) {
1268
1274
return optionParser .createEntry (loc , loc , flag );
1269
1275
}
@@ -1420,4 +1426,22 @@ public boolean equals(Object obj) {
1420
1426
return true ;
1421
1427
}
1422
1428
1429
+ private static <K , V > V threadSafeComputeIfAbsent (K key , HashMap <K , V > cacheMap ,
1430
+ Function <? super K , ? extends V > mappingFunction , ReentrantReadWriteLock rwLock ) {
1431
+ rwLock .readLock ().lock ();
1432
+ V value = cacheMap .get (key );
1433
+ rwLock .readLock ().unlock ();
1434
+ if (value != null ) {
1435
+ return value ;
1436
+ }
1437
+
1438
+ rwLock .writeLock ().lock ();
1439
+ value = cacheMap .get (key );
1440
+ if (value == null ) {
1441
+ value = cacheMap .computeIfAbsent (key , mappingFunction );
1442
+ }
1443
+ rwLock .writeLock ().unlock ();
1444
+
1445
+ return value ;
1446
+ }
1423
1447
}
0 commit comments