Thread safety changes in objmap2 33/3933/1
authorReino Ruusu <reino.ruusu@semantum.fi>
Mon, 24 Feb 2020 11:56:41 +0000 (13:56 +0200)
committerReino Ruusu <reino.ruusu@semantum.fi>
Wed, 26 Feb 2020 12:10:40 +0000 (14:10 +0200)
gitlab #483

Change-Id: I3a831732961ff7fc3ac6db3a2fdb94c2e9361d7a

12 files changed:
bundles/org.simantics.objmap2/src/org/simantics/objmap/forward/IForwardMappingRule.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/annotations/factories/UpdateMethodFactory.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/Mapping.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/impl/RangeUpdateRequest.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/MappedElementRule.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/MappedElementsRule.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/rules/ValueRule.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/schema/AdaptedLinkType.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/graph/schema/SimpleLinkType.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/structural/annotations/factories/UpdateMethodFactory.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/structural/schema/AdaptedLinkType.java
bundles/org.simantics.objmap2/src/org/simantics/objmap/structural/schema/SimpleLinkType.java

index d6c707e026b5e5f1086f19599d2d7591d2650a8d..27a1aeb1af216883eb0e686382541abb8bc13025 100644 (file)
@@ -15,6 +15,11 @@ import org.simantics.db.ReadGraph;
 import org.simantics.objmap.exceptions.MappingException;
 
 public interface IForwardMappingRule<Domain, Range> {
+       /**
+        * Check whether a range element needs to be updated due to a change in the range element, without modifying the range element.
+        */
+       boolean checkChanges(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;
+       
        /**
         * Modifies the range element so that it corresponds to the domain element.
         * @param g read transaction
@@ -24,6 +29,6 @@ public interface IForwardMappingRule<Domain, Range> {
         * @return true if the rule made some modifications
         * @throws MappingException
         */
-       boolean updateRange(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException; 
+       boolean updateRange(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;
        void createRange(ReadGraph graph, IForwardMapping<Domain, Range> mapping, Domain domainElement, Range rangeElement) throws MappingException;
 }
index e1de9f20c20c0983a4ea4c2fe15d40c0db872e04..79c39ecfac2b6713da40eb8d828feb5c6f8c8088 100644 (file)
@@ -58,6 +58,12 @@ public class UpdateMethodFactory<Domain, Range> implements IMethodRuleFactory<Do
                 return false;
             }
             
+            @Override
+            public boolean checkChanges(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement,
+                    Range rangeElement) throws MappingException {
+                return false;
+            }
+            
             public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
                updateDomain(g, map, domainElement, rangeElement);
             };
index 1589e94326ef2be74755dbd1e114895bdc111ca1..4820dae016b44c358fe52206d876f25a66b42fe3 100644 (file)
@@ -12,8 +12,6 @@
 package org.simantics.objmap.graph.impl;
 
 
-import gnu.trove.map.hash.THashMap;
-
 import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -21,12 +19,9 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.exception.DatabaseException;
-
 import org.simantics.objmap.backward.IBackwardMapping;
 import org.simantics.objmap.exceptions.MappingException;
 import org.simantics.objmap.forward.IForwardMapping;
@@ -34,6 +29,10 @@ import org.simantics.objmap.graph.IMapping;
 import org.simantics.objmap.graph.IMappingListener;
 import org.simantics.objmap.graph.schema.ILinkType;
 import org.simantics.objmap.graph.schema.IMappingSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.map.hash.THashMap;
 
 /**
  * An implementation of IMapping. The class should not be created
@@ -306,13 +305,15 @@ public class Mapping<Domain, Range> implements IMapping<Domain, Range> {
                        
                        if(listensDomain) {
                            RangeUpdateRequest<Domain,Range> request = new RangeUpdateRequest<Domain,Range>(link, map, this);
+                           boolean changes;
                            try {
-                    g.syncRequest(request, request);
+                               changes = g.syncRequest(request, request) > 0;
                 } catch (DatabaseException e) {
                     throw new MappingException(e);
                 }
-                           // TODO check if really modified
-                           updated.add(link.rangeElement);
+                           
+                           if (changes)
+                               updated.add(link.rangeElement);
                        }
                        else
                            if(link.type.updateRange(g, map, link.domainElement, link.rangeElement))
index b84b9c94ff8b866eb8ecea86471914d6dc7d1bda..d62435cd1de24a11748be77b99928a28649f86e4 100644 (file)
@@ -21,7 +21,7 @@ import org.simantics.objmap.forward.IForwardMapping;
 import org.simantics.objmap.graph.impl.Link;
 
 
-public class RangeUpdateRequest<Domain,Range> implements Read<Boolean>, SyncListener<Boolean> {
+public class RangeUpdateRequest<Domain,Range> implements Read<Integer>, SyncListener<Integer> {
 
     Link<Domain,Range> link;
     /*
@@ -30,27 +30,24 @@ public class RangeUpdateRequest<Domain,Range> implements Read<Boolean>, SyncList
      */
     IForwardMapping<Domain, Range> map; // map==null is used to flag that request is performed once
     Mapping<Domain, Range> mapping; // mapping==null is used as a flag the request disposed
+    int counter;
     
     public RangeUpdateRequest(Link<Domain,Range> link, IForwardMapping<Domain,Range> map, Mapping<Domain,Range> mapping) {
         this.link = link;
         this.map = map;
         this.mapping = mapping;
+        this.counter = 0;
     }
 
     @Override
-    public Boolean perform(ReadGraph g) throws DatabaseException {
-        if(map != null) {
-            link.type.updateRange(g, map, link.domainElement, link.rangeElement);
-            map = null;
-            return Boolean.TRUE;
-        }
-        else if(mapping != null) {
-            mapping.domainModified(link);
-            mapping = null;
-            return Boolean.FALSE;
-        }
-        else
-            return null;
+    public Integer perform(ReadGraph g) throws DatabaseException {
+        boolean changed = false;
+        if (map != null)
+            changed = link.type.checkChanges(g, map, link.domainElement, link.rangeElement);
+        else if (mapping != null)
+            changed = link.type.checkChanges(g, mapping, link.domainElement, link.rangeElement);
+        
+        return changed ? counter + 1 : counter;
     }
     
     @Override
@@ -63,15 +60,24 @@ public class RangeUpdateRequest<Domain,Range> implements Read<Boolean>, SyncList
     }
 
     @Override
-    public void execute(ReadGraph graph, Boolean result)
-            throws DatabaseException {       
+    public void execute(ReadGraph graph, Integer result)
+            throws DatabaseException {
+        boolean changed = result != counter;
+        counter = result;
+        
+        if (map != null) {
+            if (changed)
+                link.type.updateRange(graph, map, link.domainElement, link.rangeElement);
+            map = null;
+        }
+        else if (mapping != null && changed) {
+            mapping.domainModified(link);
+            mapping = null;
+        }
     }
 
     @Override
     public boolean isDisposed() {
         return mapping == null || link.removed || mapping.isDisposed();
     }
-    
-    
-    
 }
index 9761f555568fbc6b3827eaa2d6cd7ee77e9ad884..a0b7befed3951850a64c7816ad0902f13ca75058 100644 (file)
@@ -11,6 +11,8 @@
  *******************************************************************************/
 package org.simantics.objmap.graph.rules;
 
+import java.util.Objects;
+
 import org.simantics.db.ReadGraph;
 import org.simantics.db.WriteGraph;
 import org.simantics.objmap.backward.IBackwardMapping;
@@ -61,10 +63,19 @@ public class MappedElementRule<Domain, Range> implements IBidirectionalMappingRu
         return rangeAccessor.set(rangeElement, mappedValue);
        }       
        
+       @Override
+       public boolean checkChanges(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement, Range rangeElement) throws MappingException {
+           Domain value = domainAccessor.get(g, domainElement);
+           Range mappedValue = value == null ? null : map.map(g, value);
+           return mappedValue == rangeAccessor.get(rangeElement);
+       }
+       
+    @Override
        public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
                updateDomain(g, map, domainElement, rangeElement);
        };
        
+    @Override
        public void createRange(ReadGraph g, IForwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
                updateRange(g, map, domainElement, rangeElement);
        };
index 7f3c13a106e956989fc4185353de667adad5f6e1..45fe7064111ad017022d9a8d90caedba7e01694f 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.objmap.graph.rules;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Objects;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.WriteGraph;
@@ -66,12 +67,25 @@ public class MappedElementsRule<Domain, Range> implements IBidirectionalMappingR
             Domain domainElement, Range rangeElement)
     throws MappingException {
         LOGGER.trace("    MappedElementsRule.updateRange");
-        Collection<Domain> value = domainAccessor.get(g, domainElement);
+        ArrayList<Range> mappedValue = getMappedValue(g, map, domainElement);
+        return rangeAccessor.set(rangeElement, mappedValue);
+    }
+    
+    @Override
+    public boolean checkChanges(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement, Range rangeElement) throws MappingException {
+        LOGGER.trace("    MappedElementsRule.updateRange");
+        ArrayList<Range> mappedValue = getMappedValue(g, map, domainElement);
+        return Objects.equals(mappedValue, rangeAccessor.get(rangeElement));
+    }
+
+       private ArrayList<Range> getMappedValue(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement)
+                       throws MappingException {
+               Collection<Domain> value = domainAccessor.get(g, domainElement);
         ArrayList<Range> mappedValue = new ArrayList<Range>(value.size());
         for(Domain r : value)
             mappedValue.add(map.map(g, r));//map.get(r));
-        return rangeAccessor.set(rangeElement, mappedValue);
-    }
+               return mappedValue;
+       }
     
     public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
        updateDomain(g, map, domainElement, rangeElement);
index 9ba9dba11274291b0dadb6664492542bd853951e..cbea3253a9135fd403d81c016eacd2cae8ad2377 100644 (file)
@@ -13,6 +13,9 @@ package org.simantics.objmap.graph.rules;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+
 import org.simantics.db.ReadGraph;
 import org.simantics.db.WriteGraph;
 import org.simantics.objmap.backward.IBackwardMapping;
@@ -57,7 +60,14 @@ public class ValueRule<Domain, Range> implements IBidirectionalMappingRule<Domai
         LOGGER.trace("    ValueRule.updateRange");
                Object value = domainAccessor.get(g, domainElement);
                return rangeAccessor.set(rangeElement, value);
-       }       
+       }
+       
+       @Override
+       public boolean checkChanges(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement,
+                       Range rangeElement) throws MappingException {
+               Object value = rangeAccessor.get(rangeElement);
+               return Objects.equals(value, domainAccessor.get(g, domainElement));
+       }
        
        public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
                updateDomain(g, map, domainElement, rangeElement);
index 9b02d5d50c9bec9d4bcb77ed9a1277fd6c015267..b0d8d965f087ff9be1f098c48c01f144bf6a6839 100644 (file)
@@ -69,18 +69,27 @@ public class AdaptedLinkType<Range> implements ILinkType<Resource,Range> {
        }
     }
     
+    @Override
     public void createDomain(WriteGraph graph, IBackwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {
        
     };
     
+    @Override
     public void createRange(ReadGraph graph, org.simantics.objmap.forward.IForwardMapping<Resource,Range> mapping, Resource domainElement, Range rangeElement) throws MappingException {
        
     };
     
+    @Override
+    public boolean checkChanges(ReadGraph g, IForwardMapping<Resource, Range> map, Resource domainElement, Range rangeElement) throws MappingException {
+       return false;
+    }
+    
+    @Override
     public boolean updateDomain(WriteGraph g, IBackwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {
        return false;
     }
     
+    @Override
     public boolean updateRange(ReadGraph g, IForwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {
        return false;
     }
index 9ddc437162e12a32720c5faefa6544ddc7e8a246..12dd4c9c03ed6bc5c8442fc5c15083fa893676e6 100644 (file)
@@ -104,6 +104,15 @@ public class SimpleLinkType<Range> implements ILinkType<Resource,Range> {
        updateRange(graph, mapping, domainElement, rangeElement);
     };
     
+    @Override
+    public boolean checkChanges(ReadGraph g, IForwardMapping<Resource, Range> map, Resource domainElement,
+            Range rangeElement) throws MappingException {
+        boolean updated = false;
+        for(IBidirectionalMappingRule<Resource, Range> rule : rules)
+            updated |= rule.checkChanges(g, map, domainElement, rangeElement);
+        return updated;
+    }
+    
     public boolean updateDomain(WriteGraph g, IBackwardMapping<Resource,Range> map, Resource domainElement, Range rangeElement) throws MappingException {
         if(LOGGER.isTraceEnabled())
             try { 
index a2be5fa42bf978083642deb38b68807e46dc3329..c0fee3da6e53c27ed6042c23e58ed881c5fa5564 100644 (file)
@@ -58,6 +58,12 @@ public class UpdateMethodFactory<Domain, Range> implements IMethodRuleFactory<Do
                 return false;
             }
             
+            @Override
+            public boolean checkChanges(ReadGraph g, IForwardMapping<Domain, Range> map, Domain domainElement,
+                    Range rangeElement) throws MappingException {
+                return false;
+            }
+            
             public void createDomain(WriteGraph g, IBackwardMapping<Domain,Range> map, Domain domainElement, Range rangeElement) throws MappingException {
                updateDomain(g, map, domainElement, rangeElement);
             };
index 203863a6c74c61606d26e71d9c9dabf5964d675f..21d1d89903cfbad8dc76cf21918e6d75e24f0551 100644 (file)
@@ -72,18 +72,27 @@ public class AdaptedLinkType implements ILinkType<StructuralResource,IStructural
        }
     }
     
+    @Override
     public void createDomain(WriteGraph graph, IBackwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
        
     };
     
+    @Override
     public void createRange(ReadGraph graph, org.simantics.objmap.forward.IForwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
        
     };
     
+    @Override
+    public boolean checkChanges(ReadGraph graph, IForwardMapping<StructuralResource, IStructuralObject> mapping, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
+       return false;
+    }
+
+    @Override
     public boolean updateDomain(WriteGraph g, IBackwardMapping<StructuralResource, IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
        return false;
     }
     
+    @Override
     public boolean updateRange(ReadGraph g, IForwardMapping<StructuralResource, IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
        return false;
     }
index 77b2ab094a50b6baf05c6853b3b10a7da6d91242..5df6064b85225d1729d56a7b32f4ac36bd0a513e 100644 (file)
@@ -154,6 +154,15 @@ public class SimpleLinkType implements ILinkType<StructuralResource,IStructuralO
        updateRange(graph, mapping, domainElement, rangeElement);
     }
     
+    @Override
+    public boolean checkChanges(ReadGraph g, IForwardMapping<StructuralResource, IStructuralObject> map,
+            StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
+        boolean updated = false;
+        for(IBidirectionalMappingRule<StructuralResource, IStructuralObject> rule : rules)
+            updated |= rule.checkChanges(g, map, domainElement, rangeElement);
+        return updated;
+    }
+    
     public boolean updateDomain(WriteGraph g, IBackwardMapping<StructuralResource,IStructuralObject> map, StructuralResource domainElement, IStructuralObject rangeElement) throws MappingException {
         if(LOGGER.isTraceEnabled())
             try {