]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Hopeful objmap/h2d fixes:
authorlehtonen <lehtonen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 16 Mar 2010 23:10:01 +0000 (23:10 +0000)
committerlehtonen <lehtonen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 16 Mar 2010 23:10:01 +0000 (23:10 +0000)
 - Made h2d Diagram elements list a synchronized collection, i.e. Vector to allow objmap to directly access it without causing race conditions
 - Changed objmap MappedElementsRule to snapshot the collection returned by IRangeAccessor before iterating it to prevent ConcurrentModificationExceptions from happening. Atomic snapshotting is not possible if the accessed range Collection field is not a synchronized/concurrent structure.

git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@15008 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.h2d/src/org/simantics/h2d/diagram/Diagram.java
org.simantics.objmap/src/org/simantics/objmap/rules/MappedElementsRule.java

index dc9e4a813cd458b8cc73b1c91c6b090fcbf78162..673a5be8aff6c69ae2ba9ec3de9f6642eaacd08b 100644 (file)
@@ -13,16 +13,17 @@ package org.simantics.h2d.diagram;
 \r
 import java.util.ArrayList;\r
 import java.util.List;\r
+import java.util.Vector;\r
 \r
 import org.simantics.h2d.element.IElement;\r
-import org.simantics.objmap.annotations.RelatedValue;\r
 import org.simantics.objmap.annotations.GraphType;\r
+import org.simantics.objmap.annotations.RelatedValue;\r
 \r
 @GraphType("http://www.simantics.org/Sysdyn-1.0/Configuration")\r
 public class Diagram implements IDiagram {\r
 \r
     @RelatedValue("http://www.simantics.org/Layer0-1.0/ConsistsOf")\r
-       public ArrayList<IElement> elements = new ArrayList<IElement>();\r
+       public List<IElement> elements = new Vector<IElement>();\r
        ArrayList<IDiagramListener> listeners = new ArrayList<IDiagramListener>();\r
        \r
        @Override\r
index 9cfb92f27e08b4c4630cc17f43bb74aa3e8c2e9a..4d754abd5c54b40af29a4a8ee9a17273060301fb 100644 (file)
@@ -31,39 +31,44 @@ import org.simantics.objmap.rules.range.IRangeAccessor;
  * @author Hannu Niemistö\r
  */\r
 public class MappedElementsRule implements IMappingRule {\r
-    \r
+\r
     static Logger LOGGER = Logger.getLogger("org.simantics.objmap");\r
-    \r
-       IDomainAccessor<Collection<Resource>> domainAccessor;\r
-       IRangeAccessor<Collection<Object>> rangeAccessor;\r
-       \r
-       public MappedElementsRule(IDomainAccessor<Collection<Resource>> domainAccessor,\r
-                       IRangeAccessor<Collection<Object>> rangeAccessor) {\r
-               this.domainAccessor = domainAccessor;\r
-               this.rangeAccessor = rangeAccessor;\r
-       }\r
 \r
-       @Override\r
-       public boolean updateDomain(WriteGraph g, IFunction<Object, Resource> map,\r
-                       Resource domainElement, Object rangeElement)\r
-                       throws MappingException {\r
-           LOGGER.info("    MappedElementsRule.updateDomain");\r
-           Collection<Object> value = rangeAccessor.get(rangeElement);\r
-           ArrayList<Resource> mappedValue = new ArrayList<Resource>(value.size());\r
-           for(Object obj : value)\r
-               mappedValue.add(map.get(obj));\r
-               return domainAccessor.set(g, domainElement, mappedValue);\r
-       }\r
+    IDomainAccessor<Collection<Resource>> domainAccessor;\r
+    IRangeAccessor<Collection<Object>> rangeAccessor;\r
+    Object[] rangeSnapshot = new Object[0];\r
+\r
+    public MappedElementsRule(IDomainAccessor<Collection<Resource>> domainAccessor,\r
+            IRangeAccessor<Collection<Object>> rangeAccessor) {\r
+        this.domainAccessor = domainAccessor;\r
+        this.rangeAccessor = rangeAccessor;\r
+    }\r
+\r
+    @Override\r
+    public boolean updateDomain(WriteGraph g, IFunction<Object, Resource> map,\r
+            Resource domainElement, Object rangeElement)\r
+    throws MappingException {\r
+        LOGGER.info("    MappedElementsRule.updateDomain");\r
+        // Snapshot the accessed range value for concurrency safety.\r
+        // NOTE: still assumes that the accessed collection is concurrent or\r
+        // synchronized for toArray to be atomic.\r
+        Collection<Object> value = rangeAccessor.get(rangeElement);\r
+        Object[] rangeSnapshot = value.toArray();\r
+        ArrayList<Resource> mappedValue = new ArrayList<Resource>(rangeSnapshot.length);\r
+        for (Object obj : rangeSnapshot)\r
+            mappedValue.add(map.get(obj));\r
+        return domainAccessor.set(g, domainElement, mappedValue);\r
+    }\r
 \r
-       @Override\r
-       public boolean updateRange(ReadGraph g, IFunction<Resource, Object> map,\r
-                       Resource domainElement, Object rangeElement)\r
-                       throws MappingException {\r
-           LOGGER.info("    MappedElementsRule.updateRange");\r
-           Collection<Resource> value = domainAccessor.get(g, domainElement);\r
+    @Override\r
+    public boolean updateRange(ReadGraph g, IFunction<Resource, Object> map,\r
+            Resource domainElement, Object rangeElement)\r
+    throws MappingException {\r
+        LOGGER.info("    MappedElementsRule.updateRange");\r
+        Collection<Resource> value = domainAccessor.get(g, domainElement);\r
         ArrayList<Object> mappedValue = new ArrayList<Object>(value.size());\r
         for(Resource r : value)\r
             mappedValue.add(map.get(r));\r
         return rangeAccessor.set(rangeElement, mappedValue);\r
-       }       \r
+    }\r
 }\r