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,9 +158,9 @@ 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); }
} }
/** /**
@ -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,11 +180,10 @@ 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)
l.valueChanged(addr);
for (DataListener l : listeners) }
l.valueChanged(addr);
} }
/** /**

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)
@ -110,8 +114,8 @@ public class RealTimeClock implements ModelStateObserver {
@Override @Override
public void run() { public void run() {
System.out.println("thread start"); System.out.println("thread start");
long time= System.currentTimeMillis(); long time = System.currentTimeMillis();
long counter=0; long counter = 0;
try { try {
while (!interrupted()) { while (!interrupted()) {
modelSync.accessNEx(() -> { modelSync.accessNEx(() -> {
@ -123,9 +127,9 @@ public class RealTimeClock implements ModelStateObserver {
} catch (NodeException e1) { } catch (NodeException e1) {
stopper.showErrorAndStopModel(Lang.get("msg_clockError"), e1); stopper.showErrorAndStopModel(Lang.get("msg_clockError"), e1);
} }
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;
@ -678,17 +678,17 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
statusLabel.setText(Lang.get("msg_N_nodes", model.size())); statusLabel.setText(Lang.get("msg_N_nodes", model.size()));
realtimeClockRunning = false; realtimeClockRunning = false;
modelSync=null; modelSync = null;
if (globalRunClock) if (globalRunClock)
for (Clock c : model.getClocks()) for (Clock c : model.getClocks())
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)
modelSync= NoSync.INST; modelSync = NoSync.INST;
circuitComponent.setModeAndReset(true, modelSync); circuitComponent.setModeAndReset(true, modelSync);
@ -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;
} }
} }