aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless')
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/RecursiveCommunicationGroup.java164
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/SingletonCommunicationGroup.java86
-rw-r--r--subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/TimelessCommunicationTracker.java149
3 files changed, 399 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/RecursiveCommunicationGroup.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/RecursiveCommunicationGroup.java
new file mode 100644
index 00000000..d8260384
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/RecursiveCommunicationGroup.java
@@ -0,0 +1,164 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath 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 *******************************************************************************/
9package tools.refinery.viatra.runtime.rete.network.communication.timeless;
10
11import java.util.Collection;
12import java.util.Collections;
13import java.util.EnumMap;
14import java.util.LinkedHashSet;
15import java.util.Map;
16import java.util.Set;
17
18import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory;
19import tools.refinery.viatra.runtime.rete.network.Node;
20import tools.refinery.viatra.runtime.rete.network.RederivableNode;
21import tools.refinery.viatra.runtime.rete.network.communication.CommunicationGroup;
22import tools.refinery.viatra.runtime.rete.network.communication.CommunicationTracker;
23import tools.refinery.viatra.runtime.rete.network.communication.MessageSelector;
24import tools.refinery.viatra.runtime.rete.network.communication.PhasedSelector;
25import tools.refinery.viatra.runtime.rete.network.mailbox.Mailbox;
26
27/**
28 * A communication group representing either a single node where the
29 * node is a monotonicity aware one or a set of nodes that form an SCC.
30 *
31 * @author Tamas Szabo
32 * @since 2.4
33 */
34public class RecursiveCommunicationGroup extends CommunicationGroup {
35
36 private final Set<Mailbox> antiMonotoneMailboxes;
37 private final Set<Mailbox> monotoneMailboxes;
38 private final Set<Mailbox> defaultMailboxes;
39 private final Set<RederivableNode> rederivables;
40 private boolean currentlyDelivering;
41
42 /**
43 * @since 1.7
44 */
45 public RecursiveCommunicationGroup(final CommunicationTracker tracker, final Node representative, final int identifier) {
46 super(tracker, representative, identifier);
47 this.antiMonotoneMailboxes = CollectionsFactory.createSet();
48 this.monotoneMailboxes = CollectionsFactory.createSet();
49 this.defaultMailboxes = CollectionsFactory.createSet();
50 this.rederivables = new LinkedHashSet<RederivableNode>();
51 this.currentlyDelivering = false;
52 }
53
54 @Override
55 public void deliverMessages() {
56 this.currentlyDelivering = true;
57
58 // ANTI-MONOTONE PHASE
59 while (!this.antiMonotoneMailboxes.isEmpty() || !this.defaultMailboxes.isEmpty()) {
60 while (!this.antiMonotoneMailboxes.isEmpty()) {
61 final Mailbox mailbox = this.antiMonotoneMailboxes.iterator().next();
62 this.antiMonotoneMailboxes.remove(mailbox);
63 mailbox.deliverAll(PhasedSelector.ANTI_MONOTONE);
64 }
65 while (!this.defaultMailboxes.isEmpty()) {
66 final Mailbox mailbox = this.defaultMailboxes.iterator().next();
67 this.defaultMailboxes.remove(mailbox);
68 mailbox.deliverAll(PhasedSelector.DEFAULT);
69 }
70 }
71
72 // REDERIVE PHASE
73 while (!this.rederivables.isEmpty()) {
74 // re-derivable nodes take care of their unregistration!!
75 final RederivableNode node = this.rederivables.iterator().next();
76 node.rederiveOne();
77 }
78
79 // MONOTONE PHASE
80 while (!this.monotoneMailboxes.isEmpty() || !this.defaultMailboxes.isEmpty()) {
81 while (!this.monotoneMailboxes.isEmpty()) {
82 final Mailbox mailbox = this.monotoneMailboxes.iterator().next();
83 this.monotoneMailboxes.remove(mailbox);
84 mailbox.deliverAll(PhasedSelector.MONOTONE);
85 }
86 while (!this.defaultMailboxes.isEmpty()) {
87 final Mailbox mailbox = this.defaultMailboxes.iterator().next();
88 this.defaultMailboxes.remove(mailbox);
89 mailbox.deliverAll(PhasedSelector.DEFAULT);
90 }
91 }
92
93 this.currentlyDelivering = false;
94 }
95
96 @Override
97 public boolean isEmpty() {
98 return this.rederivables.isEmpty() && this.antiMonotoneMailboxes.isEmpty()
99 && this.monotoneMailboxes.isEmpty() && this.defaultMailboxes.isEmpty();
100 }
101
102 @Override
103 public void notifyHasMessage(final Mailbox mailbox, final MessageSelector kind) {
104 final Collection<Mailbox> mailboxes = getMailboxContainer(kind);
105 mailboxes.add(mailbox);
106 if (!this.isEnqueued && !this.currentlyDelivering) {
107 this.tracker.activateUnenqueued(this);
108 }
109 }
110
111 @Override
112 public void notifyLostAllMessages(final Mailbox mailbox, final MessageSelector kind) {
113 final Collection<Mailbox> mailboxes = getMailboxContainer(kind);
114 mailboxes.remove(mailbox);
115 if (isEmpty()) {
116 this.tracker.deactivate(this);
117 }
118 }
119
120 private Collection<Mailbox> getMailboxContainer(final MessageSelector kind) {
121 if (kind == PhasedSelector.ANTI_MONOTONE) {
122 return this.antiMonotoneMailboxes;
123 } else if (kind == PhasedSelector.MONOTONE) {
124 return this.monotoneMailboxes;
125 } else if (kind == PhasedSelector.DEFAULT) {
126 return this.defaultMailboxes;
127 } else {
128 throw new IllegalArgumentException(UNSUPPORTED_MESSAGE_KIND + kind);
129 }
130 }
131
132 public void addRederivable(final RederivableNode node) {
133 this.rederivables.add(node);
134 if (!this.isEnqueued) {
135 this.tracker.activateUnenqueued(this);
136 }
137 }
138
139 public void removeRederivable(final RederivableNode node) {
140 this.rederivables.remove(node);
141 if (isEmpty()) {
142 this.tracker.deactivate(this);
143 }
144 }
145
146 public Collection<RederivableNode> getRederivables() {
147 return this.rederivables;
148 }
149
150 @Override
151 public Map<MessageSelector, Collection<Mailbox>> getMailboxes() {
152 Map<PhasedSelector, Collection<Mailbox>> map = new EnumMap<>(PhasedSelector.class);
153 map.put(PhasedSelector.ANTI_MONOTONE, antiMonotoneMailboxes);
154 map.put(PhasedSelector.MONOTONE, monotoneMailboxes);
155 map.put(PhasedSelector.DEFAULT, defaultMailboxes);
156 return Collections.unmodifiableMap(map);
157 }
158
159 @Override
160 public boolean isRecursive() {
161 return true;
162 }
163
164}
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/SingletonCommunicationGroup.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/SingletonCommunicationGroup.java
new file mode 100644
index 00000000..c51c7dbf
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/SingletonCommunicationGroup.java
@@ -0,0 +1,86 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath 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 *******************************************************************************/
9package tools.refinery.viatra.runtime.rete.network.communication.timeless;
10
11import java.util.Collection;
12import java.util.Collections;
13import java.util.Map;
14
15import tools.refinery.viatra.runtime.rete.network.Node;
16import tools.refinery.viatra.runtime.rete.network.communication.CommunicationGroup;
17import tools.refinery.viatra.runtime.rete.network.communication.CommunicationTracker;
18import tools.refinery.viatra.runtime.rete.network.communication.MessageSelector;
19import tools.refinery.viatra.runtime.rete.network.communication.PhasedSelector;
20import tools.refinery.viatra.runtime.rete.network.mailbox.Mailbox;
21
22/**
23 * A communication group containing only a single node with a single default
24 * mailbox.
25 *
26 * @author Tamas Szabo
27 * @since 1.6
28 */
29public class SingletonCommunicationGroup extends CommunicationGroup {
30
31 private Mailbox mailbox;
32
33 /**
34 * @since 1.7
35 */
36 public SingletonCommunicationGroup(final CommunicationTracker tracker, final Node representative, final int identifier) {
37 super(tracker, representative, identifier);
38 }
39
40 @Override
41 public void deliverMessages() {
42 this.mailbox.deliverAll(PhasedSelector.DEFAULT);
43 }
44
45 @Override
46 public boolean isEmpty() {
47 return this.mailbox == null;
48 }
49
50 @Override
51 public void notifyHasMessage(final Mailbox mailbox, final MessageSelector kind) {
52 if (kind == PhasedSelector.DEFAULT) {
53 this.mailbox = mailbox;
54 if (!this.isEnqueued) {
55 this.tracker.activateUnenqueued(this);
56 }
57 } else {
58 throw new IllegalArgumentException(UNSUPPORTED_MESSAGE_KIND + kind);
59 }
60 }
61
62 @Override
63 public void notifyLostAllMessages(final Mailbox mailbox, final MessageSelector kind) {
64 if (kind == PhasedSelector.DEFAULT) {
65 this.mailbox = null;
66 this.tracker.deactivate(this);
67 } else {
68 throw new IllegalArgumentException(UNSUPPORTED_MESSAGE_KIND + kind);
69 }
70 }
71
72 @Override
73 public Map<MessageSelector, Collection<Mailbox>> getMailboxes() {
74 if (mailbox != null) {
75 return Collections.singletonMap(PhasedSelector.DEFAULT, Collections.singleton(mailbox));
76 } else {
77 return Collections.emptyMap();
78 }
79 }
80
81 @Override
82 public boolean isRecursive() {
83 return false;
84 }
85
86}
diff --git a/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/TimelessCommunicationTracker.java b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/TimelessCommunicationTracker.java
new file mode 100644
index 00000000..1c18c1cd
--- /dev/null
+++ b/subprojects/viatra-runtime-rete/src/main/java/tools/refinery/viatra/runtime/rete/network/communication/timeless/TimelessCommunicationTracker.java
@@ -0,0 +1,149 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2019, Tamas Szabo, Istvan Rath 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 *******************************************************************************/
9package tools.refinery.viatra.runtime.rete.network.communication.timeless;
10
11import java.util.Collection;
12import java.util.HashSet;
13import java.util.Set;
14import java.util.Map.Entry;
15
16import tools.refinery.viatra.runtime.rete.index.DualInputNode;
17import tools.refinery.viatra.runtime.rete.index.Indexer;
18import tools.refinery.viatra.runtime.rete.index.IndexerListener;
19import tools.refinery.viatra.runtime.rete.index.IterableIndexer;
20import tools.refinery.viatra.runtime.rete.network.Node;
21import tools.refinery.viatra.runtime.rete.network.Receiver;
22import tools.refinery.viatra.runtime.rete.network.RederivableNode;
23import tools.refinery.viatra.runtime.rete.network.communication.CommunicationGroup;
24import tools.refinery.viatra.runtime.rete.network.communication.CommunicationTracker;
25import tools.refinery.viatra.runtime.rete.network.communication.MessageSelector;
26import tools.refinery.viatra.runtime.rete.network.mailbox.Mailbox;
27import tools.refinery.viatra.runtime.rete.network.mailbox.timeless.BehaviorChangingMailbox;
28
29/**
30 * Timeless implementation of the communication tracker.
31 *
32 * @author Tamas Szabo
33 * @since 2.2
34 */
35public class TimelessCommunicationTracker extends CommunicationTracker {
36
37 @Override
38 protected CommunicationGroup createGroup(Node representative, int index) {
39 final boolean isSingleton = this.sccInformationProvider.sccs.getPartition(representative).size() == 1;
40 final boolean isReceiver = representative instanceof Receiver;
41 final boolean isPosetIndifferent = isReceiver
42 && ((Receiver) representative).getMailbox() instanceof BehaviorChangingMailbox;
43 final boolean isSingletonInDRedMode = isSingleton && (representative instanceof RederivableNode)
44 && ((RederivableNode) representative).isInDRedMode();
45
46 CommunicationGroup group = null;
47 // we can only use a singleton group iff
48 // (1) the SCC has one node AND
49 // (2) either we have a poset-indifferent mailbox OR the node is not even a receiver AND
50 // (3) the node does not run in DRed mode in a singleton group
51 if (isSingleton && (isPosetIndifferent || !isReceiver) && !isSingletonInDRedMode) {
52 group = new SingletonCommunicationGroup(this, representative, index);
53 } else {
54 group = new RecursiveCommunicationGroup(this, representative, index);
55 }
56
57 return group;
58 }
59
60 @Override
61 protected void reconstructQueueContents(final Set<CommunicationGroup> oldActiveGroups) {
62 for (final CommunicationGroup oldGroup : oldActiveGroups) {
63 for (final Entry<MessageSelector, Collection<Mailbox>> entry : oldGroup.getMailboxes().entrySet()) {
64 for (final Mailbox mailbox : entry.getValue()) {
65 final CommunicationGroup newGroup = this.groupMap.get(mailbox.getReceiver());
66 newGroup.notifyHasMessage(mailbox, entry.getKey());
67 }
68 }
69
70 if (oldGroup instanceof RecursiveCommunicationGroup) {
71 for (final RederivableNode node : ((RecursiveCommunicationGroup) oldGroup).getRederivables()) {
72 final CommunicationGroup newGroup = this.groupMap.get(node);
73 if (!(newGroup instanceof RecursiveCommunicationGroup)) {
74 throw new IllegalStateException("The new group must also be recursive! " + newGroup);
75 }
76 ((RecursiveCommunicationGroup) newGroup).addRederivable(node);
77 }
78 }
79 }
80 }
81
82 @Override
83 public Mailbox proxifyMailbox(final Node requester, final Mailbox original) {
84 return original;
85 }
86
87 @Override
88 public IndexerListener proxifyIndexerListener(final Node requester, final IndexerListener original) {
89 return original;
90 }
91
92 @Override
93 protected void postProcessNode(final Node node) {
94 if (node instanceof Receiver) {
95 final Mailbox mailbox = ((Receiver) node).getMailbox();
96 if (mailbox instanceof BehaviorChangingMailbox) {
97 final CommunicationGroup group = this.groupMap.get(node);
98 final Set<Node> sccNodes = this.sccInformationProvider.sccs.getPartition(node);
99 // a default mailbox must split its messages iff
100 // (1) its receiver is in a recursive group and
101 final boolean c1 = group.isRecursive();
102 // (2) its receiver is at the SCC boundary of that group
103 final boolean c2 = isAtSCCBoundary(node);
104 // (3) its group consists of more than one node
105 final boolean c3 = sccNodes.size() > 1;
106 ((BehaviorChangingMailbox) mailbox).setSplitFlag(c1 && c2 && c3);
107 }
108 }
109 }
110
111 @Override
112 protected void postProcessGroup(final CommunicationGroup group) {
113
114 }
115
116 /**
117 * @since 2.0
118 */
119 private boolean isAtSCCBoundary(final Node node) {
120 final CommunicationGroup ownGroup = this.groupMap.get(node);
121 assert ownGroup != null;
122 for (final Node source : this.dependencyGraph.getSourceNodes(node).distinctValues()) {
123 final Set<Node> sourcesToCheck = new HashSet<Node>();
124 sourcesToCheck.add(source);
125 // DualInputNodes must be checked additionally because they do not use a mailbox directly.
126 // It can happen that their indexers actually belong to other SCCs.
127 if (source instanceof DualInputNode) {
128 final DualInputNode dualInput = (DualInputNode) source;
129 final IterableIndexer primarySlot = dualInput.getPrimarySlot();
130 if (primarySlot != null) {
131 sourcesToCheck.add(primarySlot.getActiveNode());
132 }
133 final Indexer secondarySlot = dualInput.getSecondarySlot();
134 if (secondarySlot != null) {
135 sourcesToCheck.add(secondarySlot.getActiveNode());
136 }
137 }
138 for (final Node current : sourcesToCheck) {
139 final CommunicationGroup otherGroup = this.groupMap.get(current);
140 assert otherGroup != null;
141 if (!ownGroup.equals(otherGroup)) {
142 return true;
143 }
144 }
145 }
146 return false;
147 }
148
149}