some miner cleanups according synchronisation

This commit is contained in:
hneemann 2016-07-10 10:23:08 +02:00
parent 5f9cd232f8
commit 4a0ee2e513
7 changed files with 53 additions and 30 deletions

View File

@ -17,7 +17,7 @@ public class TruthTableTableModel implements TableModel {
public static final String[] STATENAMES = new String[]{"0", "1", "x"}; public static final String[] STATENAMES = new String[]{"0", "1", "x"};
private final TruthTable truthTable; private final TruthTable truthTable;
private ArrayList<TableModelListener> listeners = new ArrayList<>(); private final ArrayList<TableModelListener> listeners = new ArrayList<>();
/** /**
* Creates a new instance * Creates a new instance

View File

@ -20,7 +20,7 @@ public class DataField {
private long[] data; private long[] data;
private final int bits; private final int bits;
private transient ArrayList<DataListener> listeners; private final transient ArrayList<DataListener> listeners = new ArrayList<>();
/** /**
* Creates a new DataField * Creates a new DataField
@ -158,10 +158,10 @@ public class DataField {
* @param l the listener * @param l the listener
*/ */
public void addListener(DataListener l) { public void addListener(DataListener l) {
if (listeners == null) synchronized (listeners) {
listeners = new ArrayList<>();
listeners.add(l); listeners.add(l);
} }
}
/** /**
* Removes a listener * Removes a listener
@ -169,12 +169,9 @@ public class DataField {
* @param l the listener to remove * @param l the listener to remove
*/ */
public void removeListener(DataListener l) { public void removeListener(DataListener l) {
if (listeners == null) synchronized (listeners) {
return;
listeners.remove(l); listeners.remove(l);
if (listeners.isEmpty()) }
listeners = null;
} }
/** /**
@ -183,12 +180,11 @@ public class DataField {
* @param addr the address which value has changed * @param addr the address which value has changed
*/ */
public void fireChanged(int addr) { public void fireChanged(int addr) {
if (listeners == null) synchronized (listeners) {
return;
for (DataListener l : listeners) for (DataListener l : listeners)
l.valueChanged(addr); l.valueChanged(addr);
} }
}
/** /**
* The listener interface * The listener interface

View File

@ -4,6 +4,7 @@ import de.neemann.digital.core.*;
import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.core.wiring.Clock;
import de.neemann.digital.gui.ErrorStopper; import de.neemann.digital.gui.ErrorStopper;
import de.neemann.digital.gui.GuiModelObserver; import de.neemann.digital.gui.GuiModelObserver;
import de.neemann.digital.gui.StatusInterface;
import de.neemann.digital.gui.sync.Sync; import de.neemann.digital.gui.sync.Sync;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
@ -21,6 +22,7 @@ public class RealTimeClock implements ModelStateObserver {
private final ScheduledThreadPoolExecutor executor; private final ScheduledThreadPoolExecutor executor;
private final ErrorStopper stopper; private final ErrorStopper stopper;
private final Sync modelSync; private final Sync modelSync;
private final StatusInterface status;
private final int frequency; private final int frequency;
private final ObservableValue output; private final ObservableValue output;
private Runner runner; private Runner runner;
@ -31,12 +33,14 @@ public class RealTimeClock implements ModelStateObserver {
* @param model the model * @param model the model
* @param clock the clock element which is modify * @param clock the clock element which is modify
* @param executor the executor used to schedule the update * @param executor the executor used to schedule the update
* @param status allows sending messages to the status line
*/ */
public RealTimeClock(Model model, Clock clock, ScheduledThreadPoolExecutor executor, ErrorStopper stopper, Sync modelSync) { public RealTimeClock(Model model, Clock clock, ScheduledThreadPoolExecutor executor, ErrorStopper stopper, Sync modelSync, StatusInterface status) {
this.model = model; this.model = model;
this.executor = executor; this.executor = executor;
this.stopper = stopper; this.stopper = stopper;
this.modelSync = modelSync; this.modelSync = modelSync;
this.status = status;
int f = clock.getFrequency(); int f = clock.getFrequency();
if (f < 1) f = 1; if (f < 1) f = 1;
this.frequency = f; this.frequency = f;
@ -48,7 +52,7 @@ public class RealTimeClock implements ModelStateObserver {
switch (event) { switch (event) {
case STARTED: case STARTED:
if (frequency > 50) // if frequency is high it is not necessary to update the GUI at every clock change if (frequency > 50) // if frequency is high it is not necessary to update the GUI at every clock change
output.removeObserver(GuiModelObserver.class); modelSync.access(() -> output.removeObserver(GuiModelObserver.class));
int delay = 500000 / frequency; int delay = 500000 / frequency;
if (delay < 10) if (delay < 10)
@ -125,7 +129,7 @@ public class RealTimeClock implements ModelStateObserver {
} }
time = System.currentTimeMillis() - time; time = System.currentTimeMillis() - time;
System.out.println(counter/time/2+"kHz"); status.setStatus(counter / time / 2 + "kHz");
System.out.println("thread end"); System.out.println("thread end");
} }

View File

@ -59,7 +59,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
* *
* @author hneemann * @author hneemann
*/ */
public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, ErrorStopper, FileHistory.OpenInterface, DigitalRemoteInterface { public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, ErrorStopper, FileHistory.OpenInterface, DigitalRemoteInterface, StatusInterface {
private static final ArrayList<Key> ATTR_LIST = new ArrayList<>(); private static final ArrayList<Key> ATTR_LIST = new ArrayList<>();
private static boolean experimental; private static boolean experimental;
@ -684,7 +684,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
if (c.getFrequency() > 0) { if (c.getFrequency() > 0) {
if (modelSync == null) if (modelSync == null)
modelSync = new LockSync(); modelSync = new LockSync();
model.addObserver(new RealTimeClock(model, c, timerExecuter, this, modelSync)); model.addObserver(new RealTimeClock(model, c, timerExecuter, this, modelSync, this));
realtimeClockRunning = true; realtimeClockRunning = true;
} }
if (modelSync == null) if (modelSync == null)
@ -841,6 +841,11 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
return windowPosManager; return windowPosManager;
} }
@Override
public void setStatus(String message) {
SwingUtilities.invokeLater(() -> statusLabel.setText(message));
}
private class FullStepObserver implements Observer { private class FullStepObserver implements Observer {
private final Model model; private final Model model;

View File

@ -0,0 +1,15 @@
package de.neemann.digital.gui;
/**
* Interface to acess the status line
*
* @author hneemann
*/
public interface StatusInterface {
/**
* Set message to the status line
*
* @param message the message
*/
void setStatus(String message);
}

View File

@ -17,6 +17,10 @@ import javax.swing.*;
import static de.neemann.digital.core.element.PinInfo.input; import static de.neemann.digital.core.element.PinInfo.input;
/** /**
* Graphic card.
* Mostly a RAM module with an additional input bit which selects the visible bank.
* So you can use double buffering.
*
* @author hneemann * @author hneemann
*/ */
public class GraphicCard extends Node implements Element, RAMInterface { public class GraphicCard extends Node implements Element, RAMInterface {

View File

@ -83,7 +83,6 @@ public class ROMListingDialog extends JDialog implements Observer {
list.setSelectedIndex(line); list.setSelectedIndex(line);
}); });
} }
lastAddr = addr; lastAddr = addr;
} }
} }