@@ -156,10 +156,7 @@ private static class NativeStringTracking {
156156 //public static final int ALIGN_8 = 6;
157157
158158 protected static final int CALCULATE_SIZE = -1 ;
159- static final ReentrantReadWriteLock layoutInfoLock = new ReentrantReadWriteLock ();
160- static final ReentrantReadWriteLock fieldOrderLock = new ReentrantReadWriteLock ();
161- static final ReentrantReadWriteLock fieldListLock = new ReentrantReadWriteLock ();
162- static final ReentrantReadWriteLock validationLock = new ReentrantReadWriteLock ();
159+ static final ReentrantReadWriteLock cacheStructureLock = new ReentrantReadWriteLock ();
163160 static final Map <Class <?>, LayoutInfo > layoutInfo = new WeakHashMap <>();
164161 static final Map <Class <?>, List <String >> fieldOrder = new WeakHashMap <>();
165162 static final Map <Class <?>, List <Field >> fieldList = new WeakHashMap <>();
@@ -1024,18 +1021,18 @@ protected void sortFields(List<Field> fields, List<String> names) {
10241021 protected List <Field > getFieldList () {
10251022 Class <?> clazz = getClass ();
10261023 // Try to read the value under the read lock
1027- fieldListLock .readLock ().lock ();
1024+ cacheStructureLock .readLock ().lock ();
10281025 try {
10291026 List <Field > fields = fieldList .get (clazz );
10301027 if (fields != null ) {
10311028 return fields ; // Return the cached result if found
10321029 }
10331030 } finally {
1034- fieldListLock .readLock ().unlock ();
1031+ cacheStructureLock .readLock ().unlock ();
10351032 }
10361033
10371034 // If not found, compute the value under the write lock
1038- fieldListLock .writeLock ().lock ();
1035+ cacheStructureLock .writeLock ().lock ();
10391036 try {
10401037 // Double-check if another thread has computed the value before we do
10411038 return fieldList .computeIfAbsent (clazz , (c ) -> {
@@ -1057,7 +1054,7 @@ protected List<Field> getFieldList() {
10571054 return flist ;
10581055 });
10591056 } finally {
1060- fieldListLock .writeLock ().unlock ();
1057+ cacheStructureLock .writeLock ().unlock ();
10611058 }
10621059 }
10631060
@@ -1067,23 +1064,23 @@ protected List<Field> getFieldList() {
10671064 private List <String > fieldOrder () {
10681065 Class <?> clazz = getClass ();
10691066 // Try to read the value under the read lock
1070- fieldOrderLock .readLock ().lock ();
1067+ cacheStructureLock .readLock ().lock ();
10711068 try {
10721069 List <String > order = fieldOrder .get (clazz );
10731070 if (order != null ) {
10741071 return order ; // Return the cached result if found
10751072 }
10761073 } finally {
1077- fieldOrderLock .readLock ().unlock ();
1074+ cacheStructureLock .readLock ().unlock ();
10781075 }
10791076
10801077 // If not found, compute the value under the write lock
1081- fieldOrderLock .writeLock ().lock ();
1078+ cacheStructureLock .writeLock ().lock ();
10821079 try {
10831080 // Double-check if another thread has computed the value before we do (see JavaDoc)
10841081 return fieldOrder .computeIfAbsent (clazz , (c ) -> getFieldOrder ());
10851082 } finally {
1086- fieldOrderLock .writeLock ().unlock ();
1083+ cacheStructureLock .writeLock ().unlock ();
10871084 }
10881085 }
10891086
@@ -1198,11 +1195,11 @@ static int size(Class<? extends Structure> type) {
11981195 */
11991196 static <T extends Structure > int size (Class <T > type , T value ) {
12001197 LayoutInfo info ;
1201- layoutInfoLock .readLock ().lock ();
1198+ cacheStructureLock .readLock ().lock ();
12021199 try {
12031200 info = layoutInfo .get (type );
12041201 } finally {
1205- layoutInfoLock .readLock ().unlock ();
1202+ cacheStructureLock .readLock ().unlock ();
12061203 }
12071204 int sz = (info != null && !info .variable ) ? info .size : CALCULATE_SIZE ;
12081205 if (sz == CALCULATE_SIZE ) {
@@ -1225,11 +1222,11 @@ int calculateSize(boolean force, boolean avoidFFIType) {
12251222 int size = CALCULATE_SIZE ;
12261223 Class <?> clazz = getClass ();
12271224 LayoutInfo info ;
1228- layoutInfoLock .readLock ().lock ();
1225+ cacheStructureLock .readLock ().lock ();
12291226 try {
12301227 info = layoutInfo .get (clazz );
12311228 } finally {
1232- layoutInfoLock .readLock ().unlock ();
1229+ cacheStructureLock .readLock ().unlock ();
12331230 }
12341231 if (info == null
12351232 || this .alignType != info .alignType
@@ -1241,7 +1238,7 @@ int calculateSize(boolean force, boolean avoidFFIType) {
12411238 this .structFields = info .fields ;
12421239
12431240 if (!info .variable ) {
1244- layoutInfoLock .readLock ().lock ();
1241+ cacheStructureLock .readLock ().lock ();
12451242 try {
12461243 // If we've already cached it, only override layout if
12471244 // we're using non-default values for alignment and/or
@@ -1252,17 +1249,17 @@ int calculateSize(boolean force, boolean avoidFFIType) {
12521249 || this .alignType != ALIGN_DEFAULT
12531250 || this .typeMapper != null ) {
12541251 // Must release read lock before acquiring write lock (see JavaDoc lock escalation example)
1255- layoutInfoLock .readLock ().unlock ();
1256- layoutInfoLock .writeLock ().lock ();
1252+ cacheStructureLock .readLock ().unlock ();
1253+ cacheStructureLock .writeLock ().lock ();
12571254
12581255 layoutInfo .put (clazz , info );
12591256
12601257 // Downgrade by acquiring read lock before releasing write lock (again, see JavaDoc)
1261- layoutInfoLock .readLock ().lock ();
1262- layoutInfoLock .writeLock ().unlock ();;
1258+ cacheStructureLock .readLock ().lock ();
1259+ cacheStructureLock .writeLock ().unlock ();;
12631260 }
12641261 } finally {
1265- layoutInfoLock .readLock ().unlock ();
1262+ cacheStructureLock .readLock ().unlock ();
12661263 }
12671264 }
12681265 size = info .size ;
@@ -1307,17 +1304,17 @@ private void validateField(String name, Class<?> type) {
13071304 /** ensure all fields are of valid type. */
13081305 private void validateFields () {
13091306 // Try to read the value under the read lock
1310- validationLock .readLock ().lock ();
1307+ cacheStructureLock .readLock ().lock ();
13111308 try {
13121309 if (validationMap .containsKey (getClass ())) {
13131310 return ; // Return because this Structure has already been validated
13141311 }
13151312 } finally {
1316- validationLock .readLock ().unlock ();
1313+ cacheStructureLock .readLock ().unlock ();
13171314 }
13181315
13191316 // If not found, perform validation and update the cache under the write lock
1320- validationLock .writeLock ().lock ();
1317+ cacheStructureLock .writeLock ().lock ();
13211318 try {
13221319 // Double-check if another thread has computed the value before we do (see JavaDoc)
13231320 validationMap .computeIfAbsent (getClass (), (cls ) -> {
@@ -1327,7 +1324,7 @@ private void validateFields() {
13271324 return true ;
13281325 });
13291326 } finally {
1330- validationLock .writeLock ().unlock ();
1327+ cacheStructureLock .writeLock ().unlock ();
13311328 }
13321329 }
13331330
@@ -2214,9 +2211,7 @@ private void init(Pointer[] els) {
22142211 /** Obtain a pointer to the native FFI type descriptor for the given object. */
22152212 static FFIType get (Object obj ) {
22162213 if (obj == null )
2217- synchronized (typeInfoMap ) {
2218- return getTypeInfo (Pointer .class , 0 );
2219- }
2214+ return getTypeInfo (Pointer .class , 0 );
22202215 if (obj instanceof Class )
22212216 return get (null , (Class <?>)obj );
22222217 return get (obj , obj .getClass ());
@@ -2230,13 +2225,14 @@ private static FFIType get(Object obj, Class<?> cls) {
22302225 cls = nc .nativeType ();
22312226 }
22322227 }
2233- synchronized (typeInfoMap ) {
2234- FFIType o = getTypeInfo (cls , cls .isArray () ? Array .getLength (obj ) : 0 );
2235- if (o != null ) {
2236- return o ;
2237- }
2228+ FFIType o = getTypeInfo (cls , cls .isArray () ? Array .getLength (obj ) : 0 );
2229+ if (o != null ) {
2230+ return o ;
2231+ }
2232+ cacheStructureLock .writeLock ().lock ();
2233+ try {
22382234 if ((Platform .HAS_BUFFERS && Buffer .class .isAssignableFrom (cls ))
2239- || Callback .class .isAssignableFrom (cls )) {
2235+ || Callback .class .isAssignableFrom (cls )) {
22402236 typeInfoMap .put (cls , typeInfoMap .get (Pointer .class ));
22412237 return typeInfoMap .get (Pointer .class ).get (0 );
22422238 }
@@ -2246,30 +2242,42 @@ private static FFIType get(Object obj, Class<?> cls) {
22462242 typeInfoMap .put (cls , typeInfoMap .get (Pointer .class ));
22472243 return typeInfoMap .get (Pointer .class ).get (0 );
22482244 }
2249- FFIType type = new FFIType ((Structure )obj );
2245+ FFIType type = new FFIType ((Structure ) obj );
22502246 storeTypeInfo (cls , type );
22512247 return type ;
22522248 }
2253- if (NativeMapped .class .isAssignableFrom (cls )) {
2254- NativeMappedConverter c = NativeMappedConverter .getInstance (cls );
2255- return get (c .toNative (obj , new ToNativeContext ()), c .nativeType ());
2256- }
2257- if (cls .isArray ()) {
2258- FFIType type = new FFIType (obj , cls );
2259- // Store it in the map to prevent premature GC of type info
2260- storeTypeInfo (cls , Array .getLength (obj ), type );
2261- return type ;
2262- }
2263- throw new IllegalArgumentException ("Unsupported type " + cls );
22642249 }
2250+ finally {
2251+ cacheStructureLock .writeLock ().unlock ();
2252+ }
2253+
2254+ if (NativeMapped .class .isAssignableFrom (cls )) {
2255+ NativeMappedConverter c = NativeMappedConverter .getInstance (cls );
2256+ return get (c .toNative (obj , new ToNativeContext ()), c .nativeType ());
2257+ }
2258+
2259+ if (cls .isArray ()) {
2260+ FFIType type = new FFIType (obj , cls );
2261+ // Store it in the map to prevent premature GC of type info
2262+ storeTypeInfo (cls , Array .getLength (obj ), type );
2263+ return type ;
2264+ }
2265+
2266+ throw new IllegalArgumentException ("Unsupported type " + cls );
22652267 }
22662268
22672269 private static FFIType getTypeInfo (Class clazz , int elementCount ) {
2268- Map <Integer ,FFIType > typeMap = typeInfoMap .get (clazz );
2269- if (typeMap != null ) {
2270- return typeMap .get (elementCount );
2271- } else {
2272- return null ;
2270+ cacheStructureLock .readLock ().lock ();
2271+ try {
2272+ Map <Integer , FFIType > typeMap = typeInfoMap .get (clazz );
2273+ if (typeMap != null ) {
2274+ return typeMap .get (elementCount );
2275+ } else {
2276+ return null ;
2277+ }
2278+ }
2279+ finally {
2280+ cacheStructureLock .readLock ().unlock ();
22732281 }
22742282 }
22752283
@@ -2278,14 +2286,14 @@ private static void storeTypeInfo(Class clazz, FFIType type) {
22782286 }
22792287
22802288 private static void storeTypeInfo (Class clazz , int elementCount , FFIType type ) {
2281- synchronized (typeInfoMap ) {
2282- Map <Integer ,FFIType > typeMap = typeInfoMap .get (clazz );
2283- if (typeMap == null ) {
2284- typeMap = new HashMap <>();
2285- typeInfoMap .put (clazz , typeMap );
2286- }
2289+ cacheStructureLock .writeLock ().lock ();
2290+ try {
2291+ Map <Integer , FFIType > typeMap = typeInfoMap .computeIfAbsent (clazz , k -> new HashMap <>());
22872292 typeMap .put (elementCount , type );
22882293 }
2294+ finally {
2295+ cacheStructureLock .writeLock ().unlock ();
2296+ }
22892297 }
22902298 }
22912299
0 commit comments