You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by js...@apache.org on 2021/05/12 13:08:58 UTC

[sling-org-apache-sling-api] branch bug/SLING-10371-jsedding created (now 1156636)

This is an automated email from the ASF dual-hosted git repository.

jsedding pushed a change to branch bug/SLING-10371-jsedding
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-api.git.


      at 1156636  SLING-10371 - SlingAdaptable: ConcurrentModificationException on nested adaptTo() calls

This branch includes the following new commits:

     new 1156636  SLING-10371 - SlingAdaptable: ConcurrentModificationException on nested adaptTo() calls

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[sling-org-apache-sling-api] 01/01: SLING-10371 - SlingAdaptable: ConcurrentModificationException on nested adaptTo() calls

Posted by js...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jsedding pushed a commit to branch bug/SLING-10371-jsedding
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-api.git

commit 11566368c35ecdc6edf45d58717c1f42034bd410
Author: Julian Sedding <js...@apache.org>
AuthorDate: Wed May 12 15:08:05 2021 +0200

    SLING-10371 - SlingAdaptable: ConcurrentModificationException on nested adaptTo() calls
    
    - propose alternative fix
---
 .../apache/sling/api/adapter/SlingAdaptable.java   | 35 ++++++++++++----------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/src/main/java/org/apache/sling/api/adapter/SlingAdaptable.java b/src/main/java/org/apache/sling/api/adapter/SlingAdaptable.java
index 5adf0ce..08b337d 100644
--- a/src/main/java/org/apache/sling/api/adapter/SlingAdaptable.java
+++ b/src/main/java/org/apache/sling/api/adapter/SlingAdaptable.java
@@ -18,8 +18,10 @@
  */
 package org.apache.sling.api.adapter;
 
-import java.util.HashMap;
+import org.jetbrains.annotations.NotNull;
+
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * The <code>SlingAdaptable</code> class is an (abstract) default implementation
@@ -74,7 +76,7 @@ public abstract class SlingAdaptable implements Adaptable {
      * are intended to be short-lived to not hold on to objects and classes for
      * too long.
      */
-    private Map<Class<?>, Object> adaptersCache;
+    private volatile Map<Class<?>, Object> adaptersCache;
 
     /**
      * Calls into the registered {@link AdapterManager} to adapt this object to
@@ -94,22 +96,23 @@ public abstract class SlingAdaptable implements Adaptable {
      */
     @SuppressWarnings("unchecked")
     public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
-        AdapterType result = null;
-        synchronized ( this ) {
-            if ( adaptersCache != null ) {
-                result = (AdapterType) adaptersCache.get(type);
-            }
-            if ( result == null ) {
-                final AdapterManager mgr = ADAPTER_MANAGER;
-                result = (mgr == null ? null : mgr.getAdapter(this, type));
-                if ( result != null ) {
-                    if ( adaptersCache == null ) {
-                        adaptersCache = new HashMap<Class<?>, Object>();
-                    }
-                    adaptersCache.put(type, result);
+        final AdapterManager mgr = ADAPTER_MANAGER;
+        if (mgr == null) {
+            return null;
+        }
+        return (AdapterType) getAdaptersCache().computeIfAbsent(type, t -> mgr.getAdapter(this, t));
+    }
+
+    @NotNull
+    private Map<Class<?>, Object> getAdaptersCache() {
+        // correct use of double checked locking using volatile field
+        if (adaptersCache == null) {
+            synchronized (this) {
+                if (adaptersCache == null) {
+                    adaptersCache = new ConcurrentHashMap<>();
                 }
             }
         }
-        return result;
+        return adaptersCache;
     }
 }