mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
lots of work to clean up console lockup issues (fixes #4825)
This commit is contained in:
@@ -30,7 +30,7 @@ import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* Message console that sits below the editing area.
|
||||
* Non-GUI handling of System.out and System.err redirection.
|
||||
* <p />
|
||||
* Be careful when debugging this class, because if it's throwing exceptions,
|
||||
* don't take over System.err, and debug while watching just System.out
|
||||
@@ -43,9 +43,6 @@ import java.util.Date;
|
||||
* get along with one another. Use 'ant run' to work on encoding-related issues.
|
||||
*/
|
||||
public class Console {
|
||||
// PrintStream sketchOut;
|
||||
// PrintStream sketchErr;
|
||||
|
||||
// Single static instance shared because there's only one real System.out.
|
||||
// Within the input handlers, the currentConsole variable will be used to
|
||||
// echo things to the correct location.
|
||||
@@ -72,6 +69,13 @@ public class Console {
|
||||
|
||||
|
||||
static public void startup() {
|
||||
if (systemOut != null) {
|
||||
// TODO fix this dreadful style choice in how the Console is initialized
|
||||
// (This is not good code.. startup() should gracefully deal with this.
|
||||
// It's just a low priority relative to the likelihood of trouble.)
|
||||
new Exception("startup() called more than once").printStackTrace(systemErr);
|
||||
return;
|
||||
}
|
||||
systemOut = System.out;
|
||||
systemErr = System.err;
|
||||
|
||||
@@ -115,8 +119,6 @@ public class Console {
|
||||
File errFile = new File(consoleDir, stamp + ".err");
|
||||
stderrFile = new FileOutputStream(errFile);
|
||||
|
||||
// consoleOut = new PrintStream(new EditorConsoleStream(false, null));
|
||||
// consoleErr = new PrintStream(new EditorConsoleStream(true, null));
|
||||
consoleOut = new PrintStream(new ConsoleStream(false));
|
||||
consoleErr = new PrintStream(new ConsoleStream(true));
|
||||
|
||||
@@ -144,20 +146,14 @@ public class Console {
|
||||
}
|
||||
|
||||
|
||||
// public Console() {
|
||||
// sketchOut = new PrintStream(new EditorConsoleStream(false, this));
|
||||
// sketchErr = new PrintStream(new EditorConsoleStream(true, this));
|
||||
// }
|
||||
static public void systemOut(String what) {
|
||||
systemOut.println(what);
|
||||
}
|
||||
|
||||
|
||||
// public PrintStream getOut() {
|
||||
// return sketchOut;
|
||||
// }
|
||||
|
||||
|
||||
// public PrintStream getErr() {
|
||||
// return sketchErr;
|
||||
// }
|
||||
static public void systemErr(String what) {
|
||||
systemErr.println(what);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1997-2001 by Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
|
||||
* modify and redistribute this software in source and binary code form,
|
||||
* provided that i) this copyright notice and license appear on all copies of
|
||||
* the software; and ii) Licensee does not utilize the software in a manner
|
||||
* which is disparaging to Sun.
|
||||
*
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
|
||||
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
|
||||
@@ -25,7 +25,7 @@
|
||||
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
|
||||
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
*
|
||||
* This software is not designed or intended for use in on-line control of
|
||||
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
|
||||
* the design, construction, operation or maintenance of any nuclear
|
||||
@@ -50,7 +50,7 @@ public class StreamRedirectThread extends Thread {
|
||||
|
||||
private static final int BUFFER_SIZE = 2048;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set up for copy.
|
||||
* @param name Name of the thread
|
||||
@@ -63,15 +63,15 @@ public class StreamRedirectThread extends Thread {
|
||||
this.out = new OutputStreamWriter(out);
|
||||
setPriority(Thread.MAX_PRIORITY-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public StreamRedirectThread(String name, Reader in, Writer out) {
|
||||
super(name);
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
setPriority(Thread.MAX_PRIORITY-1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Copy.
|
||||
@@ -80,16 +80,15 @@ public class StreamRedirectThread extends Thread {
|
||||
try {
|
||||
char[] cbuf = new char[BUFFER_SIZE];
|
||||
int count;
|
||||
//System.out.println("opening streamredirectthread");
|
||||
while ((count = in.read(cbuf, 0, BUFFER_SIZE)) >= 0) {
|
||||
out.write(cbuf, 0, count);
|
||||
// had to add the flush() here.. maybe shouldn't be using writer? [fry]
|
||||
out.flush();
|
||||
}
|
||||
//System.out.println("exiting streamredirectthread");
|
||||
out.flush();
|
||||
} catch(IOException exc) {
|
||||
System.err.println("Child I/O Transfer - " + exc);
|
||||
|
||||
} catch (IOException exc) {
|
||||
processing.app.Console.systemErr("Child I/O Transfer - " + exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.MatteBorder;
|
||||
@@ -46,16 +45,6 @@ import processing.app.Preferences;
|
||||
|
||||
/**
|
||||
* Message console that sits below the editing area.
|
||||
* <p />
|
||||
* Be careful when debugging this class, because if it's throwing exceptions,
|
||||
* don't take over System.err, and debug while watching just System.out
|
||||
* or just call println() or whatever directly to systemOut or systemErr.
|
||||
* <p />
|
||||
* Also note that encodings will not work properly when run from Eclipse. This
|
||||
* means that if you use non-ASCII characters in a println() or some such,
|
||||
* the characters won't print properly in the Processing and/or Eclipse console.
|
||||
* It seems that Eclipse's console-grabbing and that of Processing don't
|
||||
* get along with one another. Use 'ant run' to work on encoding-related issues.
|
||||
*/
|
||||
public class EditorConsole extends JScrollPane {
|
||||
Editor editor;
|
||||
@@ -69,6 +58,7 @@ public class EditorConsole extends JScrollPane {
|
||||
MutableAttributeSet errStyle;
|
||||
|
||||
int maxLineCount;
|
||||
int maxCharCount;
|
||||
|
||||
PrintStream sketchOut;
|
||||
PrintStream sketchErr;
|
||||
@@ -79,9 +69,10 @@ public class EditorConsole extends JScrollPane {
|
||||
public EditorConsole(Editor editor) {
|
||||
this.editor = editor;
|
||||
|
||||
maxLineCount = Preferences.getInteger("console.length");
|
||||
maxLineCount = Preferences.getInteger("console.lines");
|
||||
maxCharCount = Preferences.getInteger("console.chars");
|
||||
|
||||
consoleDoc = new BufferedStyledDocument(10000, maxLineCount);
|
||||
consoleDoc = new BufferedStyledDocument(10000, maxLineCount, maxCharCount);
|
||||
consoleTextPane = new JTextPane(consoleDoc);
|
||||
consoleTextPane.setEditable(false);
|
||||
|
||||
@@ -98,7 +89,7 @@ public class EditorConsole extends JScrollPane {
|
||||
|
||||
protected void flush() {
|
||||
// only if new text has been added
|
||||
if (consoleDoc.hasAppendage) {
|
||||
if (consoleDoc.hasAppendage()) {
|
||||
// insert the text that's been added in the meantime
|
||||
consoleDoc.insertAll();
|
||||
// always move to the end of the text as it's added
|
||||
@@ -150,8 +141,7 @@ public class EditorConsole extends JScrollPane {
|
||||
*/
|
||||
protected void updateAppearance() {
|
||||
String fontFamily = Preferences.get("editor.font.family");
|
||||
int fontSize =
|
||||
Toolkit.zoom(Preferences.getInteger("console.font.size"));
|
||||
int fontSize = Toolkit.zoom(Preferences.getInteger("console.font.size"));
|
||||
StyleConstants.setFontFamily(stdStyle, fontFamily);
|
||||
StyleConstants.setFontSize(stdStyle, fontSize);
|
||||
StyleConstants.setFontFamily(errStyle, fontFamily);
|
||||
@@ -232,7 +222,7 @@ public class EditorConsole extends JScrollPane {
|
||||
}
|
||||
|
||||
|
||||
synchronized public void message(String what, boolean err) {
|
||||
public void message(String what, boolean err) {
|
||||
if (err && (what.contains("invalid context 0x0") || (what.contains("invalid drawable")))) {
|
||||
// Respectfully declining... This is a quirk of more recent releases of
|
||||
// Java on Mac OS X, but is widely reported as the source of any other
|
||||
@@ -302,22 +292,32 @@ public class EditorConsole extends JScrollPane {
|
||||
* swing event thread, so they need to be synchronized
|
||||
*/
|
||||
class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
List<ElementSpec> elements = new ArrayList<>();
|
||||
int maxLineLength, maxLineCount;
|
||||
//List<ElementSpec> elements = new ArrayList<>();
|
||||
LinkedBlockingQueue<ElementSpec> elements;
|
||||
// AtomicInteger queuedLineCount = new AtomicInteger();
|
||||
int maxLineLength, maxLineCount, maxCharCount;
|
||||
int currentLineLength = 0;
|
||||
boolean needLineBreak = false;
|
||||
boolean hasAppendage = false;
|
||||
// boolean hasAppendage = false;
|
||||
final Object insertLock = new Object();
|
||||
|
||||
public BufferedStyledDocument(int maxLineLength, int maxLineCount) {
|
||||
public BufferedStyledDocument(int maxLineLength, int maxLineCount,
|
||||
int maxCharCount) {
|
||||
this.maxLineLength = maxLineLength;
|
||||
this.maxLineCount = maxLineCount;
|
||||
this.maxCharCount = maxCharCount;
|
||||
elements = new LinkedBlockingQueue<>();
|
||||
}
|
||||
|
||||
// monitor this so that it's only updated when needed (otherwise console
|
||||
// updates every 250 ms when an app isn't even running.. see bug 180)
|
||||
public boolean hasAppendage() {
|
||||
return elements.size() > 0;
|
||||
}
|
||||
|
||||
/** buffer a string for insertion at the end of the DefaultStyledDocument */
|
||||
public synchronized void appendString(String str, AttributeSet a) {
|
||||
// do this so that it's only updated when needed (otherwise console
|
||||
// updates every 250 ms when an app isn't even running.. see bug 180)
|
||||
hasAppendage = true;
|
||||
public void appendString(String str, AttributeSet a) {
|
||||
// hasAppendage = true;
|
||||
|
||||
// process each line of the string
|
||||
while (str.length() > 0) {
|
||||
@@ -326,6 +326,7 @@ class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
if (needLineBreak || currentLineLength > maxLineLength) {
|
||||
elements.add(new ElementSpec(a, ElementSpec.EndTagType));
|
||||
elements.add(new ElementSpec(a, ElementSpec.StartTagType));
|
||||
// queuedLineCount.incrementAndGet();
|
||||
currentLineLength = 0;
|
||||
}
|
||||
|
||||
@@ -341,15 +342,42 @@ class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
needLineBreak = true;
|
||||
str = str.substring(str.indexOf('\n') + 1); // eat the line
|
||||
}
|
||||
/*
|
||||
while (queuedLineCount.get() > maxLineCount) {
|
||||
Console.systemOut("too many: " + queuedLineCount);
|
||||
ElementSpec elem = elements.remove();
|
||||
if (elem.getType() == ElementSpec.EndTagType) {
|
||||
queuedLineCount.decrementAndGet();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (elements.size() > 1000) {
|
||||
insertAll();
|
||||
}
|
||||
}
|
||||
|
||||
/** insert the buffered strings */
|
||||
public synchronized void insertAll() {
|
||||
ElementSpec[] elementArray = new ElementSpec[elements.size()];
|
||||
elements.toArray(elementArray);
|
||||
public void insertAll() {
|
||||
/*
|
||||
// each line is ~3 elements
|
||||
int tooMany = elements.size() - maxLineCount*3;
|
||||
if (tooMany > 0) {
|
||||
try {
|
||||
remove(0, getLength()); // clear the document first
|
||||
} catch (BadLocationException ble) {
|
||||
ble.printStackTrace();
|
||||
}
|
||||
Console.systemOut("skipping " + elements.size());
|
||||
for (int i = 0; i < tooMany; i++) {
|
||||
elements.remove();
|
||||
}
|
||||
}
|
||||
*/
|
||||
ElementSpec[] elementArray = elements.toArray(new ElementSpec[0]);
|
||||
|
||||
try {
|
||||
/*
|
||||
// check how many lines have been used so far
|
||||
// if too many, shave off a few lines from the beginning
|
||||
Element element = super.getDefaultRootElement();
|
||||
@@ -366,13 +394,42 @@ class BufferedStyledDocument extends DefaultStyledDocument {
|
||||
// remove to the end of the 200th line
|
||||
super.remove(0, endOffset);
|
||||
}
|
||||
super.insert(super.getLength(), elementArray);
|
||||
*/
|
||||
synchronized (insertLock) {
|
||||
checkLength();
|
||||
insert(getLength(), elementArray);
|
||||
checkLength();
|
||||
}
|
||||
|
||||
} catch (BadLocationException e) {
|
||||
// ignore the error otherwise this will cause an infinite loop
|
||||
// maybe not a good idea in the long run?
|
||||
}
|
||||
elements.clear();
|
||||
hasAppendage = false;
|
||||
// hasAppendage = false;
|
||||
}
|
||||
|
||||
private void checkLength() throws BadLocationException {
|
||||
// set a limit on the number of characters in the console
|
||||
int docLength = getLength();
|
||||
if (docLength > maxCharCount) {
|
||||
remove(0, docLength - maxCharCount);
|
||||
}
|
||||
// check how many lines have been used so far
|
||||
// if too many, shave off a few lines from the beginning
|
||||
Element element = super.getDefaultRootElement();
|
||||
int lineCount = element.getElementCount();
|
||||
int overage = lineCount - maxLineCount;
|
||||
if (overage > 0) {
|
||||
// if 1200 lines, and 1000 lines is max,
|
||||
// find the position of the end of the 200th line
|
||||
//systemOut.println("overage is " + overage);
|
||||
Element lineElement = element.getElement(overage);
|
||||
if (lineElement != null) {
|
||||
int endOffset = lineElement.getEndOffset();
|
||||
// remove to the end of the 200th line
|
||||
super.remove(0, endOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,8 @@ console.auto_clear = true
|
||||
|
||||
# set the maximum number of lines remembered by the console
|
||||
# the default is 500, lengthen at your own peril
|
||||
console.length = 500
|
||||
console.lines = 500
|
||||
console.chars = 40000
|
||||
|
||||
# Any additional Java options when running.
|
||||
# If you change this and can't run things, it's your own durn fault.
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
0261 (3.3.4 or 3.4)
|
||||
X redo console handling to not use Timer, fixing freeze-up problems
|
||||
o https://github.com/processing/processing/pull/4935
|
||||
X https://github.com/processing/processing/issues/4825
|
||||
|
||||
|
||||
_ should ant run launch the .app so that launchsvcs stuff works properly?
|
||||
|
||||
_ sketch.properties not being written if initial mode is p5.js?
|
||||
_ what to double-click when opening p5 projects
|
||||
@@ -39,9 +45,6 @@ _ super easy given current code implementation, might help usability
|
||||
|
||||
|
||||
contrib
|
||||
_ redo console handling to not use Timer, fixing freeze-up problems
|
||||
_ https://github.com/processing/processing/pull/4935
|
||||
_ https://github.com/processing/processing/issues/4825
|
||||
_ Make the change detector not reload the sketch
|
||||
_ https://github.com/processing/processing/pull/5021
|
||||
_ https://github.com/processing/processing/issues/4713
|
||||
|
||||
Reference in New Issue
Block a user