From: lehtonen Date: Tue, 16 Mar 2010 23:10:01 +0000 (+0000) Subject: Hopeful objmap/h2d fixes: X-Git-Tag: simantics-1.0~11 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=500d3f8c684480400e60bf5532af549377ed09a1;p=simantics%2Fsysdyn.git Hopeful objmap/h2d fixes: - 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 --- diff --git a/org.simantics.h2d/src/org/simantics/h2d/diagram/Diagram.java b/org.simantics.h2d/src/org/simantics/h2d/diagram/Diagram.java index dc9e4a81..673a5be8 100644 --- a/org.simantics.h2d/src/org/simantics/h2d/diagram/Diagram.java +++ b/org.simantics.h2d/src/org/simantics/h2d/diagram/Diagram.java @@ -13,16 +13,17 @@ package org.simantics.h2d.diagram; import java.util.ArrayList; import java.util.List; +import java.util.Vector; import org.simantics.h2d.element.IElement; -import org.simantics.objmap.annotations.RelatedValue; import org.simantics.objmap.annotations.GraphType; +import org.simantics.objmap.annotations.RelatedValue; @GraphType("http://www.simantics.org/Sysdyn-1.0/Configuration") public class Diagram implements IDiagram { @RelatedValue("http://www.simantics.org/Layer0-1.0/ConsistsOf") - public ArrayList elements = new ArrayList(); + public List elements = new Vector(); ArrayList listeners = new ArrayList(); @Override diff --git a/org.simantics.objmap/src/org/simantics/objmap/rules/MappedElementsRule.java b/org.simantics.objmap/src/org/simantics/objmap/rules/MappedElementsRule.java index 9cfb92f2..4d754abd 100644 --- a/org.simantics.objmap/src/org/simantics/objmap/rules/MappedElementsRule.java +++ b/org.simantics.objmap/src/org/simantics/objmap/rules/MappedElementsRule.java @@ -31,39 +31,44 @@ import org.simantics.objmap.rules.range.IRangeAccessor; * @author Hannu Niemistö */ public class MappedElementsRule implements IMappingRule { - + static Logger LOGGER = Logger.getLogger("org.simantics.objmap"); - - IDomainAccessor> domainAccessor; - IRangeAccessor> rangeAccessor; - - public MappedElementsRule(IDomainAccessor> domainAccessor, - IRangeAccessor> rangeAccessor) { - this.domainAccessor = domainAccessor; - this.rangeAccessor = rangeAccessor; - } - @Override - public boolean updateDomain(WriteGraph g, IFunction map, - Resource domainElement, Object rangeElement) - throws MappingException { - LOGGER.info(" MappedElementsRule.updateDomain"); - Collection value = rangeAccessor.get(rangeElement); - ArrayList mappedValue = new ArrayList(value.size()); - for(Object obj : value) - mappedValue.add(map.get(obj)); - return domainAccessor.set(g, domainElement, mappedValue); - } + IDomainAccessor> domainAccessor; + IRangeAccessor> rangeAccessor; + Object[] rangeSnapshot = new Object[0]; + + public MappedElementsRule(IDomainAccessor> domainAccessor, + IRangeAccessor> rangeAccessor) { + this.domainAccessor = domainAccessor; + this.rangeAccessor = rangeAccessor; + } + + @Override + public boolean updateDomain(WriteGraph g, IFunction map, + Resource domainElement, Object rangeElement) + throws MappingException { + LOGGER.info(" MappedElementsRule.updateDomain"); + // Snapshot the accessed range value for concurrency safety. + // NOTE: still assumes that the accessed collection is concurrent or + // synchronized for toArray to be atomic. + Collection value = rangeAccessor.get(rangeElement); + Object[] rangeSnapshot = value.toArray(); + ArrayList mappedValue = new ArrayList(rangeSnapshot.length); + for (Object obj : rangeSnapshot) + mappedValue.add(map.get(obj)); + return domainAccessor.set(g, domainElement, mappedValue); + } - @Override - public boolean updateRange(ReadGraph g, IFunction map, - Resource domainElement, Object rangeElement) - throws MappingException { - LOGGER.info(" MappedElementsRule.updateRange"); - Collection value = domainAccessor.get(g, domainElement); + @Override + public boolean updateRange(ReadGraph g, IFunction map, + Resource domainElement, Object rangeElement) + throws MappingException { + LOGGER.info(" MappedElementsRule.updateRange"); + Collection value = domainAccessor.get(g, domainElement); ArrayList mappedValue = new ArrayList(value.size()); for(Resource r : value) mappedValue.add(map.get(r)); return rangeAccessor.set(rangeElement, mappedValue); - } + } }