diff options
author | Kristóf Marussy <marussy@mit.bme.hu> | 2023-09-14 19:29:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-14 19:29:36 +0200 |
commit | 98ed3b6db5f4e51961a161050cc31c66015116e8 (patch) | |
tree | 8bfd6d9bc8d6ed23b9eb0f889dd40b6c24fe8f92 /subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java | |
parent | Merge pull request #38 from nagilooh/design-space-exploration (diff) | |
parent | Merge remote-tracking branch 'upstream/main' into partial-interpretation (diff) | |
download | refinery-98ed3b6db5f4e51961a161050cc31c66015116e8.tar.gz refinery-98ed3b6db5f4e51961a161050cc31c66015116e8.tar.zst refinery-98ed3b6db5f4e51961a161050cc31c66015116e8.zip |
Merge pull request #39 from kris7t/partial-interpretation
Implement partial interpretation based model generation
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java')
-rw-r--r-- | subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java new file mode 100644 index 00000000..9c647aa9 --- /dev/null +++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/index/SpecializedProjectionIndexer.java | |||
@@ -0,0 +1,176 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2004-2012 Gabor Bergmann and Daniel Varro | ||
3 | * This program and the accompanying materials are made available under the | ||
4 | * terms of the Eclipse Public License v. 2.0 which is available at | ||
5 | * http://www.eclipse.org/legal/epl-v20.html. | ||
6 | * | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | |||
10 | package tools.refinery.viatra.runtime.rete.index; | ||
11 | |||
12 | import java.util.ArrayList; | ||
13 | import java.util.List; | ||
14 | import java.util.Objects; | ||
15 | |||
16 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
17 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
18 | import tools.refinery.viatra.runtime.matchers.util.Direction; | ||
19 | import tools.refinery.viatra.runtime.rete.network.Node; | ||
20 | import tools.refinery.viatra.runtime.rete.network.ReteContainer; | ||
21 | import tools.refinery.viatra.runtime.rete.network.Supplier; | ||
22 | import tools.refinery.viatra.runtime.rete.network.communication.CommunicationTracker; | ||
23 | import tools.refinery.viatra.runtime.rete.network.communication.Timestamp; | ||
24 | |||
25 | /** | ||
26 | * A specialized projection indexer that can be memory-less (relying on an external source of information). | ||
27 | * | ||
28 | * <p> | ||
29 | * All specialized projection indexers of a single node will share the same listener list, so that notification order is | ||
30 | * maintained (see Bug 518434). | ||
31 | * | ||
32 | * @author Gabor Bergmann | ||
33 | * @noimplement Rely on the provided implementations | ||
34 | * @noreference Use only via standard Node and Indexer interfaces | ||
35 | * @noinstantiate This class is not intended to be instantiated by clients. | ||
36 | */ | ||
37 | public abstract class SpecializedProjectionIndexer extends StandardIndexer implements ProjectionIndexer { | ||
38 | |||
39 | protected Node activeNode; | ||
40 | protected List<ListenerSubscription> subscriptions; | ||
41 | |||
42 | /** | ||
43 | * @since 1.7 | ||
44 | */ | ||
45 | public SpecializedProjectionIndexer(final ReteContainer reteContainer, final TupleMask mask, final Supplier parent, | ||
46 | final Node activeNode, final List<ListenerSubscription> subscriptions) { | ||
47 | super(reteContainer, mask); | ||
48 | this.parent = parent; | ||
49 | this.activeNode = activeNode; | ||
50 | this.subscriptions = subscriptions; | ||
51 | } | ||
52 | |||
53 | public List<ListenerSubscription> getSubscriptions() { | ||
54 | return subscriptions; | ||
55 | } | ||
56 | |||
57 | @Override | ||
58 | public Node getActiveNode() { | ||
59 | return activeNode; | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | protected void propagate(final Direction direction, final Tuple updateElement, final Tuple signature, | ||
64 | final boolean change, final Timestamp timestamp) { | ||
65 | throw new UnsupportedOperationException(); | ||
66 | } | ||
67 | |||
68 | @Override | ||
69 | public void attachListener(final IndexerListener listener) { | ||
70 | super.attachListener(listener); | ||
71 | final CommunicationTracker tracker = this.getCommunicationTracker(); | ||
72 | final IndexerListener proxy = tracker.proxifyIndexerListener(this, listener); | ||
73 | final ListenerSubscription subscription = new ListenerSubscription(this, proxy); | ||
74 | tracker.registerDependency(this, proxy.getOwner()); | ||
75 | // See Bug 518434 | ||
76 | // Must add to the first position, so that the later listeners are notified earlier. | ||
77 | // Thus if the beta node added as listener is also an indirect descendant of the same indexer on its opposite | ||
78 | // slot, | ||
79 | // then the beta node is connected later than its ancestor's listener, therefore it will be notified earlier, | ||
80 | // eliminating duplicate insertions and lost deletions that would result from fall-through update propagation | ||
81 | subscriptions.add(0, subscription); | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public void detachListener(final IndexerListener listener) { | ||
86 | final CommunicationTracker tracker = this.getCommunicationTracker(); | ||
87 | // obtain the proxy before the super call would unregister the dependency | ||
88 | final IndexerListener proxy = tracker.proxifyIndexerListener(this, listener); | ||
89 | super.detachListener(listener); | ||
90 | final ListenerSubscription subscription = new ListenerSubscription(this, proxy); | ||
91 | final boolean wasContained = subscriptions.remove(subscription); | ||
92 | assert wasContained; | ||
93 | tracker.unregisterDependency(this, proxy.getOwner()); | ||
94 | } | ||
95 | |||
96 | @Override | ||
97 | public void networkStructureChanged() { | ||
98 | super.networkStructureChanged(); | ||
99 | final List<ListenerSubscription> oldSubscriptions = new ArrayList<ListenerSubscription>(); | ||
100 | oldSubscriptions.addAll(subscriptions); | ||
101 | subscriptions.clear(); | ||
102 | for (final ListenerSubscription oldSubscription : oldSubscriptions) { | ||
103 | // there is no need to unregister and re-register the dependency between indexer and listener | ||
104 | // because the owner of the listener is the same (even if it is proxified) | ||
105 | final CommunicationTracker tracker = this.getCommunicationTracker(); | ||
106 | // the subscriptions are shared, so we MUST reuse the indexer of the subscription instead of simply 'this' | ||
107 | final IndexerListener proxy = tracker.proxifyIndexerListener(oldSubscription.indexer, oldSubscription.listener); | ||
108 | final ListenerSubscription newSubscription = new ListenerSubscription(oldSubscription.indexer, proxy); | ||
109 | subscriptions.add(newSubscription); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * @since 2.4 | ||
115 | */ | ||
116 | public abstract void propagateToListener(IndexerListener listener, Direction direction, Tuple updateElement, | ||
117 | Timestamp timestamp); | ||
118 | |||
119 | /** | ||
120 | * Infrastructure to share subscriptions between specialized indexers of the same parent node. | ||
121 | * | ||
122 | * @author Gabor Bergmann | ||
123 | * @since 1.7 | ||
124 | */ | ||
125 | public static class ListenerSubscription { | ||
126 | protected SpecializedProjectionIndexer indexer; | ||
127 | protected IndexerListener listener; | ||
128 | |||
129 | public ListenerSubscription(SpecializedProjectionIndexer indexer, IndexerListener listener) { | ||
130 | super(); | ||
131 | this.indexer = indexer; | ||
132 | this.listener = listener; | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * @since 2.4 | ||
137 | */ | ||
138 | public SpecializedProjectionIndexer getIndexer() { | ||
139 | return indexer; | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * @since 2.4 | ||
144 | */ | ||
145 | public IndexerListener getListener() { | ||
146 | return listener; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Call this from parent node. | ||
151 | * @since 2.4 | ||
152 | */ | ||
153 | public void propagate(Direction direction, Tuple updateElement, Timestamp timestamp) { | ||
154 | indexer.propagateToListener(listener, direction, updateElement, timestamp); | ||
155 | } | ||
156 | |||
157 | @Override | ||
158 | public int hashCode() { | ||
159 | return Objects.hash(indexer, listener); | ||
160 | } | ||
161 | |||
162 | @Override | ||
163 | public boolean equals(Object obj) { | ||
164 | if (this == obj) | ||
165 | return true; | ||
166 | if (obj == null) | ||
167 | return false; | ||
168 | if (getClass() != obj.getClass()) | ||
169 | return false; | ||
170 | ListenerSubscription other = (ListenerSubscription) obj; | ||
171 | return Objects.equals(listener, other.listener) && Objects.equals(indexer, other.indexer); | ||
172 | } | ||
173 | |||
174 | } | ||
175 | |||
176 | } | ||