< prev index next >
src/share/classes/java/awt/SequencedEvent.java
Print this page
rev 13428 : 8204142: AWT hang occurs when sequenced events arrive out of sequence in multiple AppContexts
Summary: Improvements on the synchronization of SequencedEvent events from different AppContexts
Reviewed-by: serb
*** 1,7 ****
/*
! * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 23,32 ****
--- 23,33 ----
* questions.
*/
package java.awt;
+ import java.util.Iterator;
import java.util.LinkedList;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
*** 52,61 ****
--- 53,63 ----
private static final LinkedList<SequencedEvent> list = new LinkedList<>();
private final AWTEvent nested;
private AppContext appContext;
private boolean disposed;
+ private final LinkedList<AWTEvent> pendingEvents = new LinkedList<>();
static {
AWTAccessor.setSequencedEventAccessor(new AWTAccessor.SequencedEventAccessor() {
public AWTEvent getNested(AWTEvent sequencedEvent) {
return ((SequencedEvent)sequencedEvent).nested;
*** 64,73 ****
--- 66,104 ----
return event instanceof SequencedEvent;
}
});
}
+ private static final class SequencedEventsFilter implements EventFilter {
+ private final SequencedEvent currentSequencedEvent;
+ private SequencedEventsFilter(SequencedEvent currentSequencedEvent) {
+ this.currentSequencedEvent = currentSequencedEvent;
+ }
+ @Override
+ public FilterAction acceptEvent(AWTEvent ev) {
+ if (ev.getID() == ID) {
+ // Move forward dispatching only if the event is previous
+ // in SequencedEvent.list. Otherwise, hold it for reposting later.
+ synchronized (SequencedEvent.class) {
+ Iterator<SequencedEvent> it = list.iterator();
+ while (it.hasNext()) {
+ SequencedEvent iev = it.next();
+ if (iev.equals(currentSequencedEvent)) {
+ break;
+ } else if (iev.equals(ev)) {
+ return FilterAction.ACCEPT;
+ }
+ }
+ }
+ } else if (ev.getID() == SentEvent.ID) {
+ return FilterAction.ACCEPT;
+ }
+ currentSequencedEvent.pendingEvents.add(ev);
+ return FilterAction.REJECT;
+ }
+ }
+
/**
* Constructs a new SequencedEvent which will dispatch the specified
* nested event.
*
* @param nested the AWTEvent which this SequencedEvent's dispatch()
*** 102,116 ****
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
! edt.pumpEvents(SentEvent.ID, new Conditional() {
! public boolean evaluate() {
! return !SequencedEvent.this.isFirstOrDisposed();
! }
! });
} else {
while(!isFirstOrDisposed()) {
synchronized (SequencedEvent.class) {
try {
SequencedEvent.class.wait(1000);
--- 133,144 ----
if (getFirst() != this) {
if (EventQueue.isDispatchThread()) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
! edt.pumpEventsForFilter(() -> !SequencedEvent.this.isFirstOrDisposed(),
! new SequencedEventsFilter(this));
} else {
while(!isFirstOrDisposed()) {
synchronized (SequencedEvent.class) {
try {
SequencedEvent.class.wait(1000);
*** 195,208 ****
KeyboardFocusManager.getCurrentKeyboardFocusManager().
setCurrentSequencedEvent(null);
}
disposed = true;
}
- // Wake myself up
- if (appContext != null) {
- SunToolkit.postEvent(appContext, new SentEvent());
- }
SequencedEvent next = null;
synchronized (SequencedEvent.class) {
SequencedEvent.class.notifyAll();
--- 223,232 ----
*** 219,225 ****
--- 243,253 ----
}
// Wake up waiting threads
if (next != null && next.appContext != null) {
SunToolkit.postEvent(next.appContext, new SentEvent());
}
+
+ for(AWTEvent e : pendingEvents) {
+ SunToolkit.postEvent(appContext, e);
+ }
}
}
< prev index next >