23
23
24
24
package processing .app .debug ;
25
25
26
- import java .io .BufferedReader ;
27
26
import java .io .InputStream ;
28
27
import java .io .InputStreamReader ;
28
+ import java .io .Reader ;
29
29
import java .net .SocketException ;
30
30
31
31
/**
32
32
* Slurps up messages from compiler.
33
33
*/
34
34
public class MessageSiphon implements Runnable {
35
35
36
- private final BufferedReader streamReader ;
36
+ private final Reader streamReader ;
37
37
private final MessageConsumer consumer ;
38
38
39
39
private Thread thread ;
40
40
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 ;
41
45
42
46
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 );
44
52
this .consumer = consumer ;
45
53
this .canRun = true ;
54
+ this .lineTimeout = lineTimeout ;
46
55
47
56
thread = new Thread (this );
48
57
// don't set priority too low, otherwise exceptions won't
@@ -59,12 +68,46 @@ public void run() {
59
68
// (effectively sleeping the thread) until new data comes in.
60
69
// when the program is finally done, null will come through.
61
70
//
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 );
68
111
}
69
112
//EditorConsole.systemOut.println("messaging thread done");
70
113
} catch (NullPointerException npe ) {
0 commit comments