improving mock voltage slider response time by aggregating commands
This commit is contained in:
parent
8f10e85d03
commit
b023353457
|
@ -14,7 +14,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||
*
|
||||
* <p/>
|
||||
* Date: 1/7/13
|
||||
* (c) Andrey Belomutskiy
|
||||
* (c) Andrey Belomutskiy 2013-2019
|
||||
*/
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
public class CommandQueue {
|
||||
|
@ -32,7 +32,7 @@ public class CommandQueue {
|
|||
private Set<String> pendingConfirmations = Collections.synchronizedSet(new HashSet<String>());
|
||||
|
||||
private static final CommandQueue instance = new CommandQueue();
|
||||
private final BlockingQueue<MethodInvocation> pendingCommands = new LinkedBlockingQueue<>();
|
||||
private final BlockingQueue<IMethodInvocation> pendingCommands = new LinkedBlockingQueue<>();
|
||||
private final List<CommandQueueListener> commandListeners = new ArrayList<>();
|
||||
|
||||
private final Runnable runnable = new Runnable() {
|
||||
|
@ -74,7 +74,7 @@ public class CommandQueue {
|
|||
* here we block in case there is no command to send
|
||||
*/
|
||||
@NotNull
|
||||
final MethodInvocation command = pendingCommands.take();
|
||||
final IMethodInvocation command = pendingCommands.take();
|
||||
// got a command? let's send it!
|
||||
sendCommand(command);
|
||||
}
|
||||
|
@ -82,14 +82,14 @@ public class CommandQueue {
|
|||
/**
|
||||
* this method keeps retrying till a confirmation is received
|
||||
*/
|
||||
private void sendCommand(final MethodInvocation commandRequest) throws InterruptedException {
|
||||
private void sendCommand(final IMethodInvocation commandRequest) throws InterruptedException {
|
||||
int counter = 0;
|
||||
String command = commandRequest.getCommand();
|
||||
|
||||
while (!pendingConfirmations.contains(command)) {
|
||||
counter++;
|
||||
// FileLog.MAIN.logLine("templog sending " + command + " " + System.currentTimeMillis() + " " + new Date());
|
||||
LinkManager.send(command, commandRequest.fireEvent);
|
||||
LinkManager.send(command, commandRequest.isFireEvent());
|
||||
long now = System.currentTimeMillis();
|
||||
synchronized (lock) {
|
||||
lock.wait(commandRequest.getTimeout());
|
||||
|
@ -106,7 +106,7 @@ public class CommandQueue {
|
|||
}
|
||||
}
|
||||
if (pendingConfirmations.contains(command)) {
|
||||
commandRequest.listener.onCommandConfirmation();
|
||||
commandRequest.getListener().onCommandConfirmation();
|
||||
pendingConfirmations.remove(command);
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,13 @@ public class CommandQueue {
|
|||
pendingCommands.add(new MethodInvocation(command, timeoutMs, listener, fireEvent));
|
||||
}
|
||||
|
||||
static class MethodInvocation {
|
||||
public void addIfNotPresent(IMethodInvocation commandSender) {
|
||||
// technically this should be a critical locked section but for our use-case we do not care
|
||||
if (!pendingCommands.contains(commandSender))
|
||||
pendingCommands.add(commandSender);
|
||||
}
|
||||
|
||||
static class MethodInvocation implements IMethodInvocation {
|
||||
private final String command;
|
||||
private final int timeoutMs;
|
||||
private final InvocationConfirmationListener listener;
|
||||
|
@ -191,14 +197,26 @@ public class CommandQueue {
|
|||
this.fireEvent = fireEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return timeoutMs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationConfirmationListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFireEvent() {
|
||||
return fireEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MethodInvocation{" +
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package com.rusefi.io;
|
||||
|
||||
/**
|
||||
* (c) Andrey Belomutskiy 2013-2019
|
||||
*/
|
||||
public interface IMethodInvocation {
|
||||
String getCommand();
|
||||
|
||||
int getTimeout();
|
||||
|
||||
InvocationConfirmationListener getListener();
|
||||
|
||||
boolean isFireEvent();
|
||||
}
|
|
@ -3,14 +3,14 @@ package com.rusefi.ui.widgets;
|
|||
import com.rusefi.config.generated.Fields;
|
||||
import com.rusefi.core.Sensor;
|
||||
import com.rusefi.io.CommandQueue;
|
||||
import com.rusefi.io.IMethodInvocation;
|
||||
import com.rusefi.io.InvocationConfirmationListener;
|
||||
import com.rusefi.io.LinkManager;
|
||||
import com.rusefi.ui.GaugesPanel;
|
||||
import com.rusefi.ui.storage.Node;
|
||||
import com.rusefi.ui.util.UiUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
|
@ -20,9 +20,10 @@ import java.text.Format;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Hashtable;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* (c) Andrey Belomutskiy
|
||||
* (c) Andrey Belomutskiy 2013-2019
|
||||
* 11/2/14
|
||||
*/
|
||||
public class DetachedSensor {
|
||||
|
@ -82,12 +83,7 @@ public class DetachedSensor {
|
|||
}
|
||||
|
||||
void create() {
|
||||
SensorGauge.GaugeChangeListener listener = new SensorGauge.GaugeChangeListener() {
|
||||
@Override
|
||||
public void onSensorChange(Sensor sensor) {
|
||||
onChange(sensor);
|
||||
}
|
||||
};
|
||||
SensorGauge.GaugeChangeListener listener = this::onChange;
|
||||
content.add(SensorGauge.createGauge(sensor, listener, null), BorderLayout.CENTER);
|
||||
content.add(mockControlPanel, BorderLayout.SOUTH);
|
||||
|
||||
|
@ -123,8 +119,6 @@ public class DetachedSensor {
|
|||
}
|
||||
|
||||
public static Component createMockVoltageSlider(final Sensor sensor) {
|
||||
/**
|
||||
*/
|
||||
final JSlider slider = new JSlider(0, _5_VOLTS_WITH_DECIMAL);
|
||||
slider.setLabelTable(SLIDER_LABELS);
|
||||
slider.setPaintLabels(true);
|
||||
|
@ -132,12 +126,41 @@ public class DetachedSensor {
|
|||
slider.setMajorTickSpacing(10);
|
||||
slider.setMinorTickSpacing(5);
|
||||
|
||||
slider.addChangeListener(new ChangeListener() {
|
||||
AtomicReference<Double> pendingValue = new AtomicReference<>();
|
||||
|
||||
IMethodInvocation commandSender = new IMethodInvocation() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
double value = slider.getValue() / 10.0;
|
||||
CommandQueue.getInstance().write("set mock_" + sensor.name().toLowerCase() + "_voltage " + value);
|
||||
public String getCommand() {
|
||||
return "set mock_" + sensor.name().toLowerCase() + "_voltage " + pendingValue.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
return CommandQueue.DEFAULT_TIMEOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InvocationConfirmationListener getListener() {
|
||||
return InvocationConfirmationListener.VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFireEvent() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
slider.addChangeListener(e -> {
|
||||
double value = slider.getValue() / 10.0;
|
||||
CommandQueue commandQueue = CommandQueue.getInstance();
|
||||
pendingValue.set(value);
|
||||
|
||||
/*
|
||||
* User might be changing slider faster than commands are being send
|
||||
* We only add commandSender into the queue only if not already pending in order to only send one command with latest requested value and not a sequence of commands.
|
||||
*/
|
||||
commandQueue.addIfNotPresent(commandSender);
|
||||
});
|
||||
|
||||
return slider;
|
||||
|
|
Loading…
Reference in New Issue