BitDisplay, ManualSwitch now Observable. More Docs added in Timeline.
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 2 Jun 2019 13:44:42 +0000 (15:44 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 2 Jun 2019 13:45:50 +0000 (15:45 +0200)
net.mograsim.logic.core/src/net/mograsim/logic/core/components/BitDisplay.java
net.mograsim.logic.core/src/net/mograsim/logic/core/components/ManualSwitch.java
net.mograsim.logic.core/src/net/mograsim/logic/core/timeline/Timeline.java
net.mograsim.logic.core/src/net/mograsim/logic/core/wires/Wire.java
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/components/GUIManualSwitch.java
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/GUIWire.java
net.mograsim.logic.ui/src/net/mograsim/logic/ui/model/wires/WireCrossPoint.java

index bc54c23..799f412 100644 (file)
@@ -1,21 +1,27 @@
 package net.mograsim.logic.core.components;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
+import net.mograsim.logic.core.LogicObservable;
+import net.mograsim.logic.core.LogicObserver;
 import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.Bit;
 import net.mograsim.logic.core.types.BitVector;
 import net.mograsim.logic.core.wires.Wire.ReadEnd;
 import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
 
-public class BitDisplay extends BasicComponent
+public class BitDisplay extends BasicComponent implements LogicObservable
 {
+       private Collection<LogicObserver> observers;
        private final ReadEnd in;
        private BitVector displayedValue;
 
        public BitDisplay(Timeline timeline, ReadEnd in)
        {
                super(timeline, 1);
+               observers = new ArrayList<>();
                this.in = in;
                in.registerObserver(this);
                compute();
@@ -25,6 +31,7 @@ public class BitDisplay extends BasicComponent
        protected void compute()
        {
                displayedValue = in.getValues();
+               notifyObservers();
        }
 
        public BitVector getDisplayedValue()
@@ -48,4 +55,22 @@ public class BitDisplay extends BasicComponent
        {
                return List.of();
        }
+
+       @Override
+       public void registerObserver(LogicObserver ob)
+       {
+               observers.add(ob);
+       }
+
+       @Override
+       public void deregisterObserver(LogicObserver ob)
+       {
+               observers.remove(ob);
+       }
+
+       @Override
+       public void notifyObservers()
+       {
+               observers.forEach(ob -> ob.update(this));
+       }
 }
index fc6e943..e3ae372 100644 (file)
@@ -1,7 +1,11 @@
 package net.mograsim.logic.core.components;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
+import net.mograsim.logic.core.LogicObservable;
+import net.mograsim.logic.core.LogicObserver;
 import net.mograsim.logic.core.timeline.Timeline;
 import net.mograsim.logic.core.types.Bit;
 import net.mograsim.logic.core.wires.Wire.ReadEnd;
@@ -13,14 +17,16 @@ import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
  * @author Christian Femers
  *
  */
-public class ManualSwitch extends Component
+public class ManualSwitch extends Component implements LogicObservable
 {
+       private Collection<LogicObserver> observers;
        private ReadWriteEnd output;
        private boolean isOn;
 
        public ManualSwitch(Timeline timeline, ReadWriteEnd output)
        {
                super(timeline);
+               observers = new ArrayList<>();
                if (output.length() != 1)
                        throw new IllegalArgumentException("Switch output can be only a single wire");
                this.output = output;
@@ -47,6 +53,7 @@ public class ManualSwitch extends Component
                        return;
                this.isOn = isOn;
                output.feedSignals(getValue());
+               notifyObservers();
        }
 
        public boolean isOn()
@@ -71,4 +78,22 @@ public class ManualSwitch extends Component
                return List.of(output);
        }
 
+       @Override
+       public void registerObserver(LogicObserver ob)
+       {
+               observers.add(ob);
+       }
+
+       @Override
+       public void deregisterObserver(LogicObserver ob)
+       {
+               observers.remove(ob);
+       }
+
+       @Override
+       public void notifyObservers()
+       {
+               observers.forEach(ob -> ob.update(this));
+       }
+
 }
index 2dd5f97..e64c2cc 100644 (file)
@@ -21,23 +21,33 @@ public class Timeline
 
        private final List<Consumer<TimelineEvent>> eventAddedListener;
 
+       public final LongSupplier stepByStepExec = () -> lastTimeUpdated;
+       public final LongSupplier realTimeExec = () -> System.currentTimeMillis();
+
+       /**
+        * Constructs a Timeline object. Per default the time function is set to step by step execution.
+        * 
+        * @param initCapacity The initial capacity of the event queue.
+        */
        public Timeline(int initCapacity)
        {
                events = new PriorityQueue<>(initCapacity);
-
                eventAddedListener = new ArrayList<>();
-               time = () -> lastTimeUpdated;
+               time = stepByStepExec;
        }
 
        /**
         * @param timestamp exclusive
-        * @return true if the first event is later than the timestamp
+        * @return <code>true</code> if the first event in queue is later than the given timestamp
         */
        public BooleanSupplier laterThan(long timestamp)
        {
                return () -> timeCmp(events.peek().getTiming(), timestamp) > 0;
        }
 
+       /**
+        * @return <code>true</code> if there is at least one event enqueued. <code>false</code> otherwise
+        */
        public boolean hasNext()
        {
                return !events.isEmpty();
@@ -53,6 +63,9 @@ public class Timeline
                        executeUntil(laterThan(first.getTiming()), -1);
        }
 
+       /**
+        * Executes all events enqueued in the {@link Timeline}. Use very carefully! Events may generate new events, causing an infinite loop.
+        */
        public void executeAll()
        {
                while (hasNext())
@@ -71,7 +84,6 @@ public class Timeline
         * <code>EXEC_UNTIL_CONDITION</code> if the condition was met
         * <code>EXEC_UNTIL_EMPTY</code> if events were executed until the {@link Timeline} was empty
         * @formatter:on
-        * @author Christian Femers, Fabian Stemmler
         */
        public ExecutionResult executeUntil(BooleanSupplier condition, long stopMillis)
        {
@@ -97,16 +109,31 @@ public class Timeline
                return hasNext() ? ExecutionResult.EXEC_UNTIL_EMPTY : ExecutionResult.EXEC_UNTIL_CONDITION;
        }
 
+       /**
+        * Sets the function, which defines the current simulation time at any time.
+        * 
+        * @param time The return value of calling this function is the current simulation time.
+        */
        public void setTimeFunction(LongSupplier time)
        {
                this.time = time;
        }
 
+       /**
+        * Calculates the current simulation time.
+        * 
+        * @return The simulation time as defined by the time function.
+        */
        public long getSimulationTime()
        {
                return time.getAsLong();
        }
 
+       /**
+        * Retrieves the timestamp of the next event.
+        * 
+        * @return The timestamp of the next enqueued event, if the {@link Timeline} is not empty, -1 otherwise.
+        */
        public long nextEventTime()
        {
                if (!hasNext())
@@ -114,17 +141,26 @@ public class Timeline
                return events.peek().getTiming();
        }
 
+       /**
+        * Clears the {@link Timeline} of enqueued events.
+        */
        public void reset()
        {
                events.clear();
                lastTimeUpdated = 0;
        }
 
+       /**
+        * Adds a listener, that is called when a {@link TimelineEvent} is added.
+        */
        public void addEventAddedListener(Consumer<TimelineEvent> listener)
        {
                eventAddedListener.add(listener);
        }
 
+       /**
+        * Removes the listener, if possible. It will no longer be called when a {@link TimelineEvent} is added.
+        */
        public void removeEventAddedListener(Consumer<TimelineEvent> listener)
        {
                eventAddedListener.remove(listener);
@@ -185,7 +221,7 @@ public class Timeline
                }
        }
 
-       public static int timeCmp(long a, long b)
+       static int timeCmp(long a, long b)
        {
                return Long.signum(a - b);
        }
index 35addff..b26111f 100644 (file)
@@ -186,8 +186,7 @@ public class Wire
 
        private void notifyObservers()
        {
-               for (ReadEnd o : attached)
-                       o.update();
+               attached.forEach(r -> r.update());
        }
 
        /**
@@ -354,8 +353,7 @@ public class Wire
                @Override
                public void notifyObservers()
                {
-                       for (LogicObserver ob : observers)
-                               ob.update(this);
+                       observers.forEach(ob -> ob.update(this));
                }
        }
 
index 8ca57ee..a8d271e 100644 (file)
@@ -49,7 +49,7 @@ public class GUIManualSwitch extends GUIComponent
                this.logicSwitch = logicSwitch;
                this.end = end;
                // TODO when ManualSwitch supports it, add listeners
-               end.addObserver((i, o) -> callComponentLookChangedListeners());
+               end.registerObserver((i) -> callComponentLookChangedListeners());
        }
 
        @Override
index 736c0ea..c6c9432 100644 (file)
@@ -76,7 +76,7 @@ public class GUIWire
        public void setLogicModelBinding(ReadEnd end)
        {
                this.end = end;
-               end.addObserver((i, o) -> callWireLookChangedListeners());
+               end.registerObserver((i) -> callWireLookChangedListeners());
        }
 
        public Pin getPin1()
index 0949ffb..927e4e5 100644 (file)
@@ -34,7 +34,7 @@ public class WireCrossPoint extends GUIComponent
        public void setLogicModelBinding(ReadEnd end)
        {
                this.end = end;
-               end.addObserver((i, o) -> callComponentLookChangedListeners());
+               end.registerObserver((i) -> callComponentLookChangedListeners());
        }
 
        public int getLogicWidth()