mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-30 19:52:13 +01:00
Allow setting a line timeout in MessageSiphon
Previously, the MessageSiphon class would read characters from an InputStream and then push them to the passed MessageConsumer one line at a time. Now, you can specify a line timeout. Normally, messages are still processed line by line, but if no line ending is received within the specified timeout (counting from the first character in the line), then the incomplete line is passed on as a message, without waiting for the line ending. This feature is used for the uploader command output. In particular, this allows the avrdude progress bar to be shown in the IDE as expected, character by character (previously, the entire progress bar would be buffered, making it show up completely at the end of the upload).
This commit is contained in:
parent
b032f748f1
commit
d4ca6ce127
@ -102,8 +102,8 @@ public abstract class Uploader implements MessageConsumer {
|
||||
System.out.println();
|
||||
}
|
||||
Process process = ProcessUtils.exec(command);
|
||||
new MessageSiphon(process.getInputStream(), this);
|
||||
new MessageSiphon(process.getErrorStream(), this);
|
||||
new MessageSiphon(process.getInputStream(), this, 100);
|
||||
new MessageSiphon(process.getErrorStream(), this, 100);
|
||||
|
||||
// wait for the process to finish.
|
||||
result = process.waitFor();
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
package processing.app.debug;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
@ -33,16 +33,25 @@ import java.net.SocketException;
|
||||
*/
|
||||
public class MessageSiphon implements Runnable {
|
||||
|
||||
private final BufferedReader streamReader;
|
||||
private final Reader streamReader;
|
||||
private final MessageConsumer consumer;
|
||||
|
||||
private Thread thread;
|
||||
private boolean canRun;
|
||||
// Data is processed line-by-line if possible, but if this is non-zero
|
||||
// then a partial line is also processed if no line end is received
|
||||
// within this many milliseconds.
|
||||
private int lineTimeout;
|
||||
|
||||
public MessageSiphon(InputStream stream, MessageConsumer consumer) {
|
||||
this.streamReader = new BufferedReader(new InputStreamReader(stream));
|
||||
this(stream, consumer, 0);
|
||||
}
|
||||
|
||||
public MessageSiphon(InputStream stream, MessageConsumer consumer, int lineTimeout) {
|
||||
this.streamReader = new InputStreamReader(stream);
|
||||
this.consumer = consumer;
|
||||
this.canRun = true;
|
||||
this.lineTimeout = lineTimeout;
|
||||
|
||||
thread = new Thread(this);
|
||||
// don't set priority too low, otherwise exceptions won't
|
||||
@ -59,12 +68,46 @@ public class MessageSiphon implements Runnable {
|
||||
// (effectively sleeping the thread) until new data comes in.
|
||||
// when the program is finally done, null will come through.
|
||||
//
|
||||
String currentLine;
|
||||
while (canRun && (currentLine = streamReader.readLine()) != null) {
|
||||
// \n is added again because readLine() strips it out
|
||||
//EditorConsole.systemOut.println("messaging in");
|
||||
consumer.message(currentLine + "\n");
|
||||
//EditorConsole.systemOut.println("messaging out");
|
||||
StringBuilder currentLine = new StringBuilder();
|
||||
long lineStartTime = 0;
|
||||
while (canRun) {
|
||||
// First, try to read as many characters as possible. Take care
|
||||
// not to block when:
|
||||
// 1. lineTimeout is nonzero, and
|
||||
// 2. we have some characters buffered already
|
||||
while (lineTimeout == 0 || currentLine.length() == 0 || streamReader.ready()) {
|
||||
int c = streamReader.read();
|
||||
if (c == -1)
|
||||
return; // EOF
|
||||
if (!canRun)
|
||||
return;
|
||||
|
||||
// Keep track of the line start time
|
||||
if (currentLine.length() == 0)
|
||||
lineStartTime = System.nanoTime();
|
||||
|
||||
// Store the character line
|
||||
currentLine.append((char)c);
|
||||
|
||||
if (c == '\n') {
|
||||
// We read a full line, pass it on
|
||||
consumer.message(currentLine.toString());
|
||||
currentLine.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
// No more characters available. Wait until lineTimeout
|
||||
// milliseconds have passed since the start of the line and then
|
||||
// try reading again. If the time has already passed, then just
|
||||
// pass on the characters read so far.
|
||||
long passed = (System.nanoTime() - lineStartTime) / 1000;
|
||||
if (passed < this.lineTimeout) {
|
||||
Thread.sleep(this.lineTimeout - passed);
|
||||
continue;
|
||||
}
|
||||
|
||||
consumer.message(currentLine.toString());
|
||||
currentLine.setLength(0);
|
||||
}
|
||||
//EditorConsole.systemOut.println("messaging thread done");
|
||||
} catch (NullPointerException npe) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user