2323
2424package processing .app .debug ;
2525
26- import java .io .BufferedReader ;
2726import java .io .InputStream ;
2827import java .io .InputStreamReader ;
28+ import java .io .Reader ;
2929import java .net .SocketException ;
3030
3131/**
3232 * Slurps up messages from compiler.
3333 */
3434public class MessageSiphon implements Runnable {
3535
36- private final BufferedReader streamReader ;
36+ private final Reader streamReader ;
3737 private final MessageConsumer consumer ;
3838
3939 private Thread thread ;
4040 private boolean canRun ;
41+ // Data is processed line-by-line if possible, but if this is non-zero
42+ // then a partial line is also processed if no line end is received
43+ // within this many milliseconds.
44+ private int lineTimeout ;
4145
4246 public MessageSiphon (InputStream stream , MessageConsumer consumer ) {
43- this .streamReader = new BufferedReader (new InputStreamReader (stream ));
47+ this (stream , consumer , 0 );
48+ }
49+
50+ public MessageSiphon (InputStream stream , MessageConsumer consumer , int lineTimeout ) {
51+ this .streamReader = new InputStreamReader (stream );
4452 this .consumer = consumer ;
4553 this .canRun = true ;
54+ this .lineTimeout = lineTimeout ;
4655
4756 thread = new Thread (this );
4857 // don't set priority too low, otherwise exceptions won't
@@ -59,12 +68,46 @@ public void run() {
5968 // (effectively sleeping the thread) until new data comes in.
6069 // when the program is finally done, null will come through.
6170 //
62- String currentLine ;
63- while (canRun && (currentLine = streamReader .readLine ()) != null ) {
64- // \n is added again because readLine() strips it out
65- //EditorConsole.systemOut.println("messaging in");
66- consumer .message (currentLine + "\n " );
67- //EditorConsole.systemOut.println("messaging out");
71+ StringBuilder currentLine = new StringBuilder ();
72+ long lineStartTime = 0 ;
73+ while (canRun ) {
74+ // First, try to read as many characters as possible. Take care
75+ // not to block when:
76+ // 1. lineTimeout is nonzero, and
77+ // 2. we have some characters buffered already
78+ while (lineTimeout == 0 || currentLine .length () == 0 || streamReader .ready ()) {
79+ int c = streamReader .read ();
80+ if (c == -1 )
81+ return ; // EOF
82+ if (!canRun )
83+ return ;
84+
85+ // Keep track of the line start time
86+ if (currentLine .length () == 0 )
87+ lineStartTime = System .nanoTime ();
88+
89+ // Store the character line
90+ currentLine .append ((char )c );
91+
92+ if (c == '\n' ) {
93+ // We read a full line, pass it on
94+ consumer .message (currentLine .toString ());
95+ currentLine .setLength (0 );
96+ }
97+ }
98+
99+ // No more characters available. Wait until lineTimeout
100+ // milliseconds have passed since the start of the line and then
101+ // try reading again. If the time has already passed, then just
102+ // pass on the characters read so far.
103+ long passed = (System .nanoTime () - lineStartTime ) / 1000 ;
104+ if (passed < this .lineTimeout ) {
105+ Thread .sleep (this .lineTimeout - passed );
106+ continue ;
107+ }
108+
109+ consumer .message (currentLine .toString ());
110+ currentLine .setLength (0 );
68111 }
69112 //EditorConsole.systemOut.println("messaging thread done");
70113 } catch (NullPointerException npe ) {
0 commit comments