From aadf2140ca6b835e97dfdd8c630dff2c6485408f Mon Sep 17 00:00:00 2001 From: Jakub Valtar Date: Sun, 9 Apr 2017 18:32:53 +0200 Subject: [PATCH] Synchronize input event processing Some renderers (OpenGL) fire events on background threads, which can corrupt the event queue when the sketch is not looping and multiple threads add and remove from the queue at the same time. This PR uses blocking queue to serialize enqueuing and lock to synchronize dequeuing. In the ideal case, we should be able to invoke code on the animation thread (ala invokeLater) and always dequeue events from there even when the sketch is not looping. --- core/src/processing/core/PApplet.java | 57 +++++++-------------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index b3d166223..0cc144d98 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -61,6 +61,8 @@ import java.net.*; import java.nio.charset.StandardCharsets; import java.text.*; import java.util.*; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.regex.*; import java.util.zip.*; @@ -2564,38 +2566,8 @@ public class PApplet implements PConstants { ////////////////////////////////////////////////////////////// - InternalEventQueue eventQueue = new InternalEventQueue(); - - - static class InternalEventQueue { - protected Event queue[] = new Event[10]; - protected int offset; - protected int count; - - synchronized void add(Event e) { - if (count == queue.length) { - queue = (Event[]) expand(queue); - } - queue[count++] = e; - } - - synchronized Event remove() { - if (offset == count) { - throw new RuntimeException("Nothing left on the event queue."); - } - Event outgoing = queue[offset++]; - if (offset == count) { - // All done, time to reset - offset = 0; - count = 0; - } - return outgoing; - } - - synchronized boolean available() { - return count != 0; - } - } + BlockingQueue eventQueue = new LinkedBlockingQueue<>(); + private final Object eventQueueDequeueLock = new Object[0]; /** @@ -2612,16 +2584,17 @@ public class PApplet implements PConstants { protected void dequeueEvents() { - while (eventQueue.available()) { - Event e = eventQueue.remove(); - - switch (e.getFlavor()) { - case Event.MOUSE: - handleMouseEvent((MouseEvent) e); - break; - case Event.KEY: - handleKeyEvent((KeyEvent) e); - break; + synchronized (eventQueueDequeueLock) { + while (!eventQueue.isEmpty()) { + Event e = eventQueue.remove(); + switch (e.getFlavor()) { + case Event.MOUSE: + handleMouseEvent((MouseEvent) e); + break; + case Event.KEY: + handleKeyEvent((KeyEvent) e); + break; + } } } }