diff options
author | Oszkar Semerath <Oszkar Semerath@DESKTOP-DNR7JQ7> | 2021-07-26 03:39:07 +0200 |
---|---|---|
committer | Oszkar Semerath <Oszkar Semerath@DESKTOP-DNR7JQ7> | 2021-07-26 03:39:07 +0200 |
commit | 8afcdaac3951205997f3e9cd1f175b1055c39ed8 (patch) | |
tree | c9b0ad00eab0f34daa9391dbf03321c6ac0de0d9 /Solvers | |
parent | VersionedMap interface updates: diffcursors and synchronization (diff) | |
download | VIATRA-Generator-8afcdaac3951205997f3e9cd1f175b1055c39ed8.tar.gz VIATRA-Generator-8afcdaac3951205997f3e9cd1f175b1055c39ed8.tar.zst VIATRA-Generator-8afcdaac3951205997f3e9cd1f175b1055c39ed8.zip |
Added configuration options and fixed some bugs
Diffstat (limited to 'Solvers')
4 files changed, 62 insertions, 27 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreConfiguration.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreConfiguration.java new file mode 100644 index 00000000..3dda98df --- /dev/null +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreConfiguration.java | |||
@@ -0,0 +1,19 @@ | |||
1 | package org.eclipse.viatra.solver.data.map; | ||
2 | |||
3 | public class VersionedMapStoreConfiguration { | ||
4 | /** | ||
5 | * If true root is replaced with immutable node when committed. | ||
6 | * Frees up memory by releasing immutable nodes, | ||
7 | * but it may decrease performance by recreating immutable nodes upon changes (some evidence). | ||
8 | */ | ||
9 | public boolean immutableWhenCommiting = true; | ||
10 | |||
11 | /** | ||
12 | * If true, all subnodes are cached. | ||
13 | * It decreases the memory requirements. | ||
14 | * It may increase performance by discovering existing immutable copy of a node (some evidence). | ||
15 | * Additional overhead may decrease performance (no example found). | ||
16 | * The option permits the efficient implementation of version deletion. | ||
17 | */ | ||
18 | public boolean sharedNodeCache = true; | ||
19 | } | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreImpl.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreImpl.java index b6a615ed..d9adc117 100644 --- a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreImpl.java +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/VersionedMapStoreImpl.java | |||
@@ -10,20 +10,35 @@ import org.eclipse.viatra.solver.data.map.internal.Node; | |||
10 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; | 10 | import org.eclipse.viatra.solver.data.map.internal.VersionedMapImpl; |
11 | 11 | ||
12 | public class VersionedMapStoreImpl<KEY,VALUE> implements VersionedMapStore<KEY, VALUE> { | 12 | public class VersionedMapStoreImpl<KEY,VALUE> implements VersionedMapStore<KEY, VALUE> { |
13 | // Configuration | ||
14 | final private boolean immutableWhenCommiting; | ||
15 | |||
16 | // Static data | ||
13 | protected final ContinousHashProvider<? super KEY> hashProvider; | 17 | protected final ContinousHashProvider<? super KEY> hashProvider; |
14 | protected final VALUE defaultValue; | 18 | protected final VALUE defaultValue; |
15 | 19 | ||
20 | // Dynamic data | ||
16 | final protected Map<Long, ImmutableNode<KEY,VALUE>> states; | 21 | final protected Map<Long, ImmutableNode<KEY,VALUE>> states; |
17 | final protected Map<Node<KEY,VALUE>, ImmutableNode<KEY,VALUE>> nodeCache; | 22 | final protected Map<Node<KEY,VALUE>, ImmutableNode<KEY,VALUE>> nodeCache; |
18 | protected long nextID; | 23 | protected long nextID; |
19 | 24 | ||
20 | public VersionedMapStoreImpl(ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue) { | 25 | public VersionedMapStoreImpl(ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue, VersionedMapStoreConfiguration config) { |
26 | this.immutableWhenCommiting = config.immutableWhenCommiting; | ||
27 | |||
21 | this.hashProvider = hashProvider; | 28 | this.hashProvider = hashProvider; |
22 | this.defaultValue = defaultValue; | 29 | this.defaultValue = defaultValue; |
23 | 30 | ||
24 | states = new HashMap<>(); | 31 | states = new HashMap<>(); |
25 | nextID = 0; | 32 | nextID = 0; |
26 | nodeCache = new HashMap<>(); | 33 | if(config.sharedNodeCache) { |
34 | nodeCache = new HashMap<>(); | ||
35 | } else { | ||
36 | nodeCache = null; | ||
37 | } | ||
38 | } | ||
39 | |||
40 | public VersionedMapStoreImpl(ContinousHashProvider<? super KEY> hashProvider, VALUE defaultValue) { | ||
41 | this(hashProvider,defaultValue,new VersionedMapStoreConfiguration()); | ||
27 | } | 42 | } |
28 | 43 | ||
29 | synchronized Set<Long> getStates() { | 44 | synchronized Set<Long> getStates() { |
@@ -64,7 +79,9 @@ public class VersionedMapStoreImpl<KEY,VALUE> implements VersionedMapStore<KEY, | |||
64 | "Map store run out of Id-s"); | 79 | "Map store run out of Id-s"); |
65 | long id = nextID++; | 80 | long id = nextID++; |
66 | this.states.put(id, immutable); | 81 | this.states.put(id, immutable); |
67 | //mapToUpdateRoot.setRoot(immutable); | 82 | if(this.immutableWhenCommiting) { |
83 | mapToUpdateRoot.setRoot(immutable); | ||
84 | } | ||
68 | return id; | 85 | return id; |
69 | } | 86 | } |
70 | 87 | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java index 49b98863..087c12a1 100644 --- a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/ImmutableNode.java | |||
@@ -34,7 +34,12 @@ public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | |||
34 | 34 | ||
35 | /** | 35 | /** |
36 | * Constructor that copies a mutable node to an immutable. | 36 | * Constructor that copies a mutable node to an immutable. |
37 | * @param node | 37 | * |
38 | * @param node A mutable node. | ||
39 | * @param cache A cache of existing immutable nodes. It can be used to search | ||
40 | * and place reference immutable nodes. It can be null, if no cache | ||
41 | * available. | ||
42 | * @return an immutable version of the input node. | ||
38 | */ | 43 | */ |
39 | @SuppressWarnings("unchecked") | 44 | @SuppressWarnings("unchecked") |
40 | static <KEY,VALUE> ImmutableNode<KEY,VALUE> constructImmutable(MutableNode<KEY,VALUE> node, Map<Node<KEY, VALUE>, ImmutableNode<KEY, VALUE>> cache) { | 45 | static <KEY,VALUE> ImmutableNode<KEY,VALUE> constructImmutable(MutableNode<KEY,VALUE> node, Map<Node<KEY, VALUE>, ImmutableNode<KEY, VALUE>> cache) { |
@@ -83,7 +88,9 @@ public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | |||
83 | ImmutableNode<KEY,VALUE> newImmutable = new ImmutableNode<>(resultDataMap, resultNodeMap, resultContent, resultHash); | 88 | ImmutableNode<KEY,VALUE> newImmutable = new ImmutableNode<>(resultDataMap, resultNodeMap, resultContent, resultHash); |
84 | 89 | ||
85 | // 3. save new immutable. | 90 | // 3. save new immutable. |
86 | cache.put(newImmutable, newImmutable); | 91 | if(cache != null) { |
92 | cache.put(newImmutable, newImmutable); | ||
93 | } | ||
87 | return newImmutable; | 94 | return newImmutable; |
88 | } | 95 | } |
89 | 96 | ||
@@ -132,16 +139,16 @@ public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | |||
132 | if(value == defaultValue) { | 139 | if(value == defaultValue) { |
133 | // delete | 140 | // delete |
134 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | 141 | MutableNode<KEY, VALUE> mutable = this.toMutable(); |
135 | mutable.removeEntry(selectedHashFragment); | 142 | Node<KEY, VALUE> result = mutable.removeEntry(selectedHashFragment); |
136 | return mutable; | 143 | return result; |
137 | } else if(value == content[keyIndex+1]) { | 144 | } else if(value == content[keyIndex+1]) { |
138 | // dont change | 145 | // dont change |
139 | return this; | 146 | return this; |
140 | } else { | 147 | } else { |
141 | // update existing value | 148 | // update existing value |
142 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | 149 | MutableNode<KEY, VALUE> mutable = this.toMutable(); |
143 | mutable.updateValue(value, selectedHashFragment); | 150 | Node<KEY, VALUE> result = mutable.updateValue(value, selectedHashFragment); |
144 | return mutable; | 151 | return result; |
145 | } | 152 | } |
146 | } else { | 153 | } else { |
147 | if(value == defaultValue) { | 154 | if(value == defaultValue) { |
@@ -150,13 +157,13 @@ public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | |||
150 | } else { | 157 | } else { |
151 | // add new key + value | 158 | // add new key + value |
152 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | 159 | MutableNode<KEY, VALUE> mutable = this.toMutable(); |
153 | mutable.putValue(key, value, hashProvider, defaultValue, selectedHashFragment, depth); | 160 | Node<KEY, VALUE> result = mutable.putValue(key, value, hashProvider, defaultValue, hash, depth); |
154 | return mutable; | 161 | return result; |
155 | } | 162 | } |
156 | } | 163 | } |
157 | } else if((nodeMap & bitposition)!=0) { | 164 | } else if((nodeMap & bitposition)!=0) { |
158 | 165 | ||
159 | int keyIndex = content.length-1-index(dataMap, bitposition); | 166 | int keyIndex = content.length-1-index(nodeMap, bitposition); |
160 | ImmutableNode<KEY,VALUE> subNode = (ImmutableNode<KEY,VALUE>) content[keyIndex]; | 167 | ImmutableNode<KEY,VALUE> subNode = (ImmutableNode<KEY,VALUE>) content[keyIndex]; |
161 | int newDepth = depth+1; | 168 | int newDepth = depth+1; |
162 | int newHash = newHash(hashProvider, key, hash, newDepth); | 169 | int newHash = newHash(hashProvider, key, hash, newDepth); |
@@ -166,15 +173,15 @@ public class ImmutableNode<KEY, VALUE> extends Node<KEY, VALUE> { | |||
166 | // nothing changed | 173 | // nothing changed |
167 | return this; | 174 | return this; |
168 | } else { | 175 | } else { |
169 | MutableNode<KEY, VALUE> result = toMutable(); | 176 | MutableNode<KEY, VALUE> mutable = toMutable(); |
170 | result.updateSubNode(selectedHashFragment, newsubNode); | 177 | Node<KEY, VALUE> result = mutable.updateSubNode(selectedHashFragment, newsubNode); |
171 | return result; | 178 | return result; |
172 | } | 179 | } |
173 | } else { | 180 | } else { |
174 | // add new key + value | 181 | // add new key + value |
175 | MutableNode<KEY, VALUE> mutable = this.toMutable(); | 182 | MutableNode<KEY, VALUE> mutable = this.toMutable(); |
176 | mutable.putValue(key, value, hashProvider, defaultValue, selectedHashFragment, depth); | 183 | Node<KEY, VALUE> result = mutable.putValue(key, value, hashProvider, defaultValue, hash, depth); |
177 | return mutable; | 184 | return result; |
178 | } | 185 | } |
179 | } | 186 | } |
180 | 187 | ||
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java index eaded957..c81bf36f 100644 --- a/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java +++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.solver.data/src/org/eclipse/viatra/solver/data/map/internal/MutableNode.java | |||
@@ -42,11 +42,11 @@ public class MutableNode<KEY,VALUE> extends Node<KEY,VALUE> { | |||
42 | for(int i=0; i<factor; i++) { | 42 | for(int i=0; i<factor; i++) { |
43 | int bitposition = 1 << i; | 43 | int bitposition = 1 << i; |
44 | if((node.dataMap & bitposition) != 0) { | 44 | if((node.dataMap & bitposition) != 0) { |
45 | content[2*i] = this.content[dataUsed*2]; | 45 | content[2*i] = node.content[dataUsed*2]; |
46 | content[2*i+1] = this.content[dataUsed*2+1]; | 46 | content[2*i+1] = node.content[dataUsed*2+1]; |
47 | dataUsed++; | 47 | dataUsed++; |
48 | } else if((node.nodeMap & bitposition) != 0) { | 48 | } else if((node.nodeMap & bitposition) != 0) { |
49 | content[2*i+1] = this.content[this.content.length-1-nodeUsed]; | 49 | content[2*i+1] = node.content[node.content.length-1-nodeUsed]; |
50 | nodeUsed++; | 50 | nodeUsed++; |
51 | } | 51 | } |
52 | } | 52 | } |
@@ -394,14 +394,6 @@ public class MutableNode<KEY,VALUE> extends Node<KEY,VALUE> { | |||
394 | return this.cachedHash; | 394 | return this.cachedHash; |
395 | } | 395 | } |
396 | 396 | ||
397 | public void checkHashCodeConsistency() { | ||
398 | int oldHash = this.hashCode(); | ||
399 | updateHash(); | ||
400 | int newHash = this.hashCode(); | ||
401 | if(oldHash != newHash) { | ||
402 | throw new IllegalStateException("Inconsistent hash code!"); | ||
403 | } | ||
404 | } | ||
405 | 397 | ||
406 | @Override | 398 | @Override |
407 | public boolean equals(Object obj) { | 399 | public boolean equals(Object obj) { |