< 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 >