提交 3403002c 编写于 作者: L lana

Merge

......@@ -61,85 +61,43 @@ import sun.awt.EventQueueDelegate;
* @since 1.1
*/
class EventDispatchThread extends Thread {
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
private EventQueue theQueue;
private boolean doDispatch = true;
private boolean threadDeathCaught = false;
private static final int ANY_EVENT = -1;
private Vector<EventFilter> eventFilters = new Vector<EventFilter>();
// used in handleException
private int modalFiltersCount = 0;
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
super(group, name);
theQueue = queue;
}
void stopDispatchingImpl(boolean wait) {
// Note: We stop dispatching via a flag rather than using
// Thread.interrupt() because we can't guarantee that the wait()
// we interrupt will be EventQueue.getNextEvent()'s. -fredx 8-11-98
StopDispatchEvent stopEvent = new StopDispatchEvent();
// wait for the dispatcher to complete
if (Thread.currentThread() != this) {
// fix 4122683, 4128923
// Post an empty event to ensure getNextEvent is unblocked
//
// We have to use postEventPrivate instead of postEvent because
// EventQueue.pop calls EventDispatchThread.stopDispatching.
// Calling SunToolkit.flushPendingEvents in this case could
// lead to deadlock.
theQueue.postEventPrivate(stopEvent);
if (wait) {
try {
join();
} catch(InterruptedException e) {
}
}
} else {
stopEvent.dispatch();
}
theQueue.detachDispatchThread(this, false);
setEventQueue(queue);
}
/*
* Must be called on EDT only, that's why no synchronization
*/
public void stopDispatching() {
stopDispatchingImpl(true);
}
public void stopDispatchingLater() {
stopDispatchingImpl(false);
}
class StopDispatchEvent extends AWTEvent implements ActiveEvent {
/*
* serialVersionUID
*/
static final long serialVersionUID = -3692158172100730735L;
public StopDispatchEvent() {
super(EventDispatchThread.this,0);
}
public void dispatch() {
doDispatch = false;
}
doDispatch = false;
}
public void run() {
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
return true;
while (true) {
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
return true;
}
});
} finally {
EventQueue eq = getEventQueue();
if (eq.detachDispatchThread(this) || threadDeathCaught) {
break;
}
});
} finally {
theQueue.detachDispatchThread(this, true);
}
}
}
......@@ -190,7 +148,6 @@ class EventDispatchThread extends Thread {
}
}
eventFilters.add(k, filter);
modalFiltersCount++;
} else {
eventFilters.add(filter);
}
......@@ -200,28 +157,25 @@ class EventDispatchThread extends Thread {
void removeEventFilter(EventFilter filter) {
synchronized (eventFilters) {
if (eventFilters.contains(filter)) {
if (filter instanceof ModalEventFilter) {
modalFiltersCount--;
}
eventFilters.remove(filter);
}
eventFilters.remove(filter);
}
}
boolean pumpOneEventForFilters(int id) {
AWTEvent event = null;
boolean eventOK = false;
try {
AWTEvent event;
boolean eventOK;
EventQueueDelegate.Delegate delegate =
EventQueueDelegate.getDelegate();
EventQueue eq = null;
EventQueueDelegate.Delegate delegate = null;
do {
// EventQueue may change during the dispatching
eq = getEventQueue();
delegate = EventQueueDelegate.getDelegate();
if (delegate != null && id == ANY_EVENT) {
event = delegate.getNextEvent(theQueue);
event = delegate.getNextEvent(eq);
} else {
event = (id == ANY_EVENT)
? theQueue.getNextEvent()
: theQueue.getNextEvent(id);
event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
}
eventOK = true;
......@@ -252,13 +206,15 @@ class EventDispatchThread extends Thread {
if (delegate != null) {
handle = delegate.beforeDispatch(event);
}
theQueue.dispatchEvent(event);
eq.dispatchEvent(event);
if (delegate != null) {
delegate.afterDispatch(event, handle);
}
return true;
}
catch (ThreadDeath death) {
threadDeathCaught = true;
return false;
}
......@@ -267,12 +223,10 @@ class EventDispatchThread extends Thread {
// Threads in the AppContext
}
// Can get and throw only unchecked exceptions
catch (RuntimeException e) {
processException(e);
} catch (Error e) {
catch (Throwable e) {
processException(e);
}
return true;
}
......@@ -281,14 +235,14 @@ class EventDispatchThread extends Thread {
eventLog.fine("Processing exception: " + e);
}
getUncaughtExceptionHandler().uncaughtException(this, e);
// don't rethrow the exception to avoid EDT recreation
}
boolean isDispatching(EventQueue eq) {
return theQueue.equals(eq);
public synchronized EventQueue getEventQueue() {
return theQueue;
}
public synchronized void setEventQueue(EventQueue eq) {
theQueue = eq;
}
EventQueue getEventQueue() { return theQueue; }
private static class HierarchyEventFilter implements EventFilter {
private Component modalComponent;
......
......@@ -138,6 +138,15 @@ public class EventQueue {
private final Lock pushPopLock;
private final Condition pushPopCond;
/*
* Dummy runnable to wake up EDT from getNextEvent() after
push/pop is performed
*/
private final static Runnable dummyRunnable = new Runnable() {
public void run() {
}
};
private EventDispatchThread dispatchThread;
private final ThreadGroup threadGroup =
......@@ -219,22 +228,22 @@ public class EventQueue {
* @param theEvent an instance of <code>java.awt.AWTEvent</code>,
* or a subclass of it
*/
final void postEventPrivate(AWTEvent theEvent) {
private final void postEventPrivate(AWTEvent theEvent) {
theEvent.isPosted = true;
pushPopLock.lock();
try {
if (dispatchThread == null && nextQueue == null) {
if (nextQueue != null) {
// Forward the event to the top of EventQueue stack
nextQueue.postEventPrivate(theEvent);
return;
}
if (dispatchThread == null) {
if (theEvent.getSource() == AWTAutoShutdown.getInstance()) {
return;
} else {
initDispatchThread();
}
}
if (nextQueue != null) {
// Forward event to top of EventQueue stack.
nextQueue.postEventPrivate(theEvent);
return;
}
postEvent(theEvent, getPriority(theEvent));
} finally {
pushPopLock.unlock();
......@@ -242,29 +251,20 @@ public class EventQueue {
}
private static int getPriority(AWTEvent theEvent) {
if (theEvent instanceof PeerEvent &&
(((PeerEvent)theEvent).getFlags() &
PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0)
{
return ULTIMATE_PRIORITY;
}
if (theEvent instanceof PeerEvent &&
(((PeerEvent)theEvent).getFlags() &
PeerEvent.PRIORITY_EVENT) != 0)
{
return HIGH_PRIORITY;
}
if (theEvent instanceof PeerEvent &&
(((PeerEvent)theEvent).getFlags() &
PeerEvent.LOW_PRIORITY_EVENT) != 0)
{
return LOW_PRIORITY;
if (theEvent instanceof PeerEvent) {
PeerEvent peerEvent = (PeerEvent)theEvent;
if ((peerEvent.getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
return ULTIMATE_PRIORITY;
}
if ((peerEvent.getFlags() & PeerEvent.PRIORITY_EVENT) != 0) {
return HIGH_PRIORITY;
}
if ((peerEvent.getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) {
return LOW_PRIORITY;
}
}
int id = theEvent.getID();
if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
if ((id >= PaintEvent.PAINT_FIRST) && (id <= PaintEvent.PAINT_LAST)) {
return LOW_PRIORITY;
}
return NORM_PRIORITY;
......@@ -501,16 +501,9 @@ public class EventQueue {
SunToolkit.flushPendingEvents();
pushPopLock.lock();
try {
for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
if (queues[i].head != null) {
EventQueueItem entry = queues[i].head;
queues[i].head = entry.next;
if (entry.next == null) {
queues[i].tail = null;
}
uncacheEQItem(entry);
return entry.event;
}
AWTEvent event = getNextEventPrivate();
if (event != null) {
return event;
}
AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread);
pushPopCond.await();
......@@ -520,6 +513,24 @@ public class EventQueue {
} while(true);
}
/*
* Must be called under the lock. Doesn't call flushPendingEvents()
*/
AWTEvent getNextEventPrivate() throws InterruptedException {
for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
if (queues[i].head != null) {
EventQueueItem entry = queues[i].head;
queues[i].head = entry.next;
if (entry.next == null) {
queues[i].tail = null;
}
uncacheEQItem(entry);
return entry.event;
}
}
return null;
}
AWTEvent getNextEvent(int id) throws InterruptedException {
do {
/*
......@@ -659,7 +670,9 @@ public class EventQueue {
dispatchThread.stopDispatching();
}
} else {
System.err.println("unable to dispatch event: " + event);
if (eventLog.isLoggable(PlatformLogger.FINE)) {
eventLog.fine("Unable to dispatch event: " + event);
}
}
}
......@@ -761,15 +774,23 @@ public class EventQueue {
pushPopLock.lock();
try {
EventQueue toPush = this;
while (toPush.nextQueue != null) {
toPush = toPush.nextQueue;
EventQueue topQueue = this;
while (topQueue.nextQueue != null) {
topQueue = topQueue.nextQueue;
}
if ((topQueue.dispatchThread != null) &&
(topQueue.dispatchThread.getEventQueue() == this))
{
newEventQueue.dispatchThread = topQueue.dispatchThread;
topQueue.dispatchThread.setEventQueue(newEventQueue);
}
// Transfer all events forward to new EventQueue.
while (toPush.peekEvent() != null) {
while (topQueue.peekEvent() != null) {
try {
newEventQueue.postEventPrivate(toPush.getNextEvent());
// Use getNextEventPrivate() as it doesn't call flushPendingEvents()
newEventQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
if (eventLog.isLoggable(PlatformLogger.FINE)) {
eventLog.fine("Interrupted push", ie);
......@@ -777,28 +798,21 @@ public class EventQueue {
}
}
newEventQueue.previousQueue = toPush;
/*
* Stop the event dispatch thread associated with the currently
* active event queue, so that after the new queue is pushed
* on the top this event dispatch thread won't prevent AWT from
* being automatically shut down.
* Use stopDispatchingLater() to avoid deadlock: stopDispatching()
* waits for the dispatch thread to exit, which in turn waits
* for the lock in EQ.detachDispatchThread(), which is hold by
* this method.
*/
if (toPush.dispatchThread != null) {
toPush.dispatchThread.stopDispatchingLater();
}
// Wake up EDT waiting in getNextEvent(), so it can
// pick up a new EventQueue. Post the waking event before
// topQueue.nextQueue is assigned, otherwise the event would
// go newEventQueue
topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
toPush.nextQueue = newEventQueue;
newEventQueue.previousQueue = topQueue;
topQueue.nextQueue = newEventQueue;
AppContext appContext = AppContext.getAppContext();
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) {
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) {
appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
}
pushPopCond.signalAll();
} finally {
pushPopLock.unlock();
}
......@@ -822,44 +836,51 @@ public class EventQueue {
eventLog.fine("EventQueue.pop(" + this + ")");
}
EventDispatchThread dt = null;
pushPopLock.lock();
try {
EventQueue toPop = this;
while (toPop.nextQueue != null) {
toPop = toPop.nextQueue;
EventQueue topQueue = this;
while (topQueue.nextQueue != null) {
topQueue = topQueue.nextQueue;
}
EventQueue prev = toPop.previousQueue;
if (prev == null) {
EventQueue prevQueue = topQueue.previousQueue;
if (prevQueue == null) {
throw new EmptyStackException();
}
toPop.previousQueue = null;
topQueue.previousQueue = null;
prevQueue.nextQueue = null;
// Transfer all events back to previous EventQueue.
prev.nextQueue = null;
while (toPop.peekEvent() != null) {
while (topQueue.peekEvent() != null) {
try {
prev.postEventPrivate(toPop.getNextEvent());
prevQueue.postEventPrivate(topQueue.getNextEventPrivate());
} catch (InterruptedException ie) {
if (eventLog.isLoggable(PlatformLogger.FINE)) {
eventLog.fine("Interrupted pop", ie);
}
}
}
if ((topQueue.dispatchThread != null) &&
(topQueue.dispatchThread.getEventQueue() == this))
{
prevQueue.dispatchThread = topQueue.dispatchThread;
topQueue.dispatchThread.setEventQueue(prevQueue);
}
AppContext appContext = AppContext.getAppContext();
if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) {
appContext.put(AppContext.EVENT_QUEUE_KEY, prev);
appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue);
}
dt = toPop.dispatchThread;
// Wake up EDT waiting in getNextEvent(), so it can
// pick up a new EventQueue
topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable));
pushPopCond.signalAll();
} finally {
pushPopLock.unlock();
}
if (dt != null) {
dt.stopDispatching(); // Must be done outside synchronized
// block to avoid possible deadlock
}
}
/**
......@@ -907,9 +928,9 @@ public class EventQueue {
try {
AppContext appContext = AppContext.getAppContext();
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
dispatchThread = (EventDispatchThread)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
dispatchThread = AccessController.doPrivileged(
new PrivilegedAction<EventDispatchThread>() {
public EventDispatchThread run() {
EventDispatchThread t =
new EventDispatchThread(threadGroup,
name,
......@@ -919,7 +940,8 @@ public class EventQueue {
t.setDaemon(false);
return t;
}
});
}
);
AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread);
dispatchThread.start();
}
......@@ -928,7 +950,7 @@ public class EventQueue {
}
}
final void detachDispatchThread(EventDispatchThread edt, boolean restart) {
final boolean detachDispatchThread(EventDispatchThread edt) {
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
......@@ -939,26 +961,21 @@ public class EventQueue {
*/
pushPopLock.lock();
try {
EventDispatchThread oldDispatchThread = dispatchThread;
if (dispatchThread == edt) {
dispatchThread = null;
}
if (restart) {
if (edt == dispatchThread) {
/*
* Event dispatch thread dies in case of an uncaught exception.
* A new event dispatch thread for this queue will be started
* only if a new event is posted to it. In case if no more
* events are posted after this thread died all events that
* currently are in the queue will never be dispatched.
* Don't detach the thread if any events are pending. Not
* sure if it's a possible scenario, though.
*
* Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue.
*/
if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) {
initDispatchThread();
return false;
}
AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread);
dispatchThread = null;
}
AWTAutoShutdown.getInstance().notifyThreadFree(edt);
return true;
} finally {
pushPopLock.unlock();
}
......
......@@ -39,6 +39,7 @@ import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import sun.util.logging.PlatformLogger;
import sun.misc.SoftCache;
......@@ -592,7 +593,7 @@ public abstract class SunToolkit extends Toolkit
}
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if(postEventQueue != null) {
if (postEventQueue != null) {
postEventQueue.postEvent(event);
}
}
......@@ -610,16 +611,29 @@ public abstract class SunToolkit extends Toolkit
postEvent(targetToAppContext(e.getSource()), pe);
}
private static final Lock flushLock = new ReentrantLock();
private static boolean isFlushingPendingEvents = false;
/*
* Flush any pending events which haven't been posted to the AWT
* EventQueue yet.
*/
public static void flushPendingEvents() {
AppContext appContext = AppContext.getAppContext();
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if(postEventQueue != null) {
postEventQueue.flush();
flushLock.lock();
try {
// Don't call flushPendingEvents() recursively
if (!isFlushingPendingEvents) {
isFlushingPendingEvents = true;
AppContext appContext = AppContext.getAppContext();
PostEventQueue postEventQueue =
(PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY);
if (postEventQueue != null) {
postEventQueue.flush();
}
}
} finally {
isFlushingPendingEvents = false;
flushLock.unlock();
}
}
......@@ -1930,6 +1944,25 @@ public abstract class SunToolkit extends Toolkit
return (Window)comp;
}
/**
* Returns the value of the system property indicated by the specified key.
*/
public static String getSystemProperty(final String key) {
return (String)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty(key);
}
});
}
/**
* Returns the boolean value of the system property indicated by the specified key.
*/
protected static Boolean getBooleanSystemProperty(String key) {
return Boolean.valueOf(AccessController.
doPrivileged(new GetBooleanAction(key)));
}
private static Boolean sunAwtDisableMixing = null;
/**
......@@ -1938,9 +1971,7 @@ public abstract class SunToolkit extends Toolkit
*/
public synchronized static boolean getSunAwtDisableMixing() {
if (sunAwtDisableMixing == null) {
sunAwtDisableMixing = Boolean.valueOf(
AccessController.doPrivileged(
new GetBooleanAction("sun.awt.disableMixing")));
sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing");
}
return sunAwtDisableMixing.booleanValue();
}
......@@ -2079,12 +2110,14 @@ class PostEventQueue {
eventQueue = eq;
}
public boolean noEvents() {
public synchronized boolean noEvents() {
return queueHead == null;
}
/*
* Continually post pending AWTEvents to the Java EventQueue.
* Continually post pending AWTEvents to the Java EventQueue. The method
* is synchronized to ensure the flush is completed before a new event
* can be posted to this queue.
*/
public synchronized void flush() {
EventQueueItem tempQueue = queueHead;
......
......@@ -1053,10 +1053,28 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
return peer;
}
private static Boolean sunAwtDisableGtkFileDialogs = null;
/**
* Returns the value of "sun.awt.disableGtkFileDialogs" property. Default
* value is {@code false}.
*/
public synchronized static boolean getSunAwtDisableGtkFileDialogs() {
if (sunAwtDisableGtkFileDialogs == null) {
sunAwtDisableGtkFileDialogs =
getBooleanSystemProperty("sun.awt.disableGtkFileDialogs");
}
return sunAwtDisableGtkFileDialogs.booleanValue();
}
public FileDialogPeer createFileDialog(FileDialog target) {
FileDialogPeer peer = null;
// The current GtkFileChooser is available from GTK+ 2.4
FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer(
target) : new XFileDialogPeer(target);
if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
peer = new GtkFileDialogPeer(target);
} else {
peer = new XFileDialogPeer(target);
}
targetCreatedPeer(target, peer);
return peer;
}
......@@ -1201,14 +1219,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
}
}
static String getSystemProperty(final String name) {
return (String)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty(name);
}
});
}
public PrintJob getPrintJob(final Frame frame, final String doctitle,
final Properties props) {
......
......@@ -778,8 +778,8 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
x, y,
xbe.get_x_root(),
xbe.get_y_root(),
clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
3,button==4 ? -1 : 1);
1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL,
3,button==4 ? -1*clickCount : 1*clickCount);
postEventToEventQueue(mwe);
}
}
......
......@@ -42,17 +42,16 @@ static gboolean filenameFilterCallback(const GtkFileFilterInfo * filter_info, gp
filename);
}
/*
* Class: sun_awt_X11_GtkFileDialogPeer
* Method: quit
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
(JNIEnv * env, jobject jpeer)
static void quit(gboolean isSignalHandler)
{
if (dialog != NULL)
{
fp_gdk_threads_enter();
// Callbacks from GTK signals are made within the GTK lock
// So, within a signal handler there is no need to call
// gdk_threads_enter() / fp_gdk_threads_leave()
if (!isSignalHandler) {
fp_gdk_threads_enter();
}
fp_gtk_widget_hide (dialog);
fp_gtk_widget_destroy (dialog);
......@@ -60,10 +59,23 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
fp_gtk_main_quit ();
dialog = NULL;
fp_gdk_threads_leave();
if (!isSignalHandler) {
fp_gdk_threads_leave();
}
}
}
/*
* Class: sun_awt_X11_GtkFileDialogPeer
* Method: quit
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit
(JNIEnv * env, jobject jpeer)
{
quit(FALSE);
}
/**
* Convert a GSList to an array of filenames (without the parent folder)
*/
......@@ -147,7 +159,7 @@ static void handle_response(GtkWidget* aDialog, gint responseId, gpointer obj)
jfilenames);
fp_g_free(current_folder);
Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL);
quit(TRUE);
}
/*
......
/*
* Copyright (c) 2010, 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
@test
@bug 6304473 6727884
......
......@@ -34,35 +34,40 @@
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import sun.awt.SunToolkit;
import test.java.awt.regtesthelpers.Util;
public class LoopRobustness {
static int clicks = 0;
final static long TIMEOUT = 5000;
final static Object LOCK = new Object();
static volatile boolean notifyOccur = false;
public static void main(String [] args) {
public static int clicks = 0;
public static volatile boolean notifyOccured = false;
public static volatile boolean otherExceptionsCaught = false;
public static void main(String [] args) throws Exception {
ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup();
long at;
//wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff.
synchronized (LoopRobustness.LOCK){
synchronized (LoopRobustness.LOCK) {
new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start();
at = System.currentTimeMillis();
try {
while(!notifyOccur && System.currentTimeMillis() - at < TIMEOUT) {
while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) {
LoopRobustness.LOCK.wait(1000);
}
} catch(InterruptedException e){
} catch (InterruptedException e) {
throw new RuntimeException("Test interrupted.", e);
}
}
if( !notifyOccur){
if (!notifyOccured) {
//notify doesn't occur after a reasonable time.
throw new RuntimeException("Test failed. Second Thread didn't notify MainThread.");
throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread");
}
//now wait for two clicks
......@@ -75,7 +80,10 @@ public class LoopRobustness {
}
}
if (clicks != 2) {
throw new RuntimeException("robot should press button twice");
throw new RuntimeException("Test FAILED: robot should press button twice");
}
if (otherExceptionsCaught) {
throw new RuntimeException("Test FAILED: unexpected exceptions caught");
}
}
}
......@@ -83,18 +91,11 @@ public class LoopRobustness {
class Impl implements Runnable{
static Robot robot;
public void run() {
SunToolkit.createNewAppContext();
Button b = new Button("Press me to test the AWT-Event Queue thread");
Frame lr = new Frame("ROBUST FRAME");
/* Must load Toolkit on this thread only, rather then on Main.
If load on Main (on the parent ThreadGroup of current ThreadGroup) then
EDT will be created on Main thread and supplied with it's own exceptionHandler,
which just throws an Exception and terminates current thread.
The test implies that EDT is created on the child ThreadGroup (testThreadGroup)
which is supplied with its own uncaughtException().
*/
Toolkit.getDefaultToolkit();
lr.setBounds(100, 100, 300, 100);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LoopRobustness.clicks++;
......@@ -107,40 +108,46 @@ class Impl implements Runnable{
try {
robot = new Robot();
} catch(AWTException e){
} catch (AWTException e) {
throw new RuntimeException("Test interrupted.", e);
}
Util.waitForIdle(robot);
synchronized (LoopRobustness.LOCK){
LoopRobustness.LOCK.notify();
LoopRobustness.notifyOccur = true;
LoopRobustness.notifyOccured = true;
}
int i = 0;
while(i < 2){
while (i < 2) {
robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2,
b.getLocationOnScreen().y + b.getHeight()/2 );
b.getLocationOnScreen().y + b.getHeight()/2);
Util.waitForIdle(robot);
robot.mousePress(InputEvent.BUTTON1_MASK);
// robot.delay(10);
Util.waitForIdle(robot);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Util.waitForIdle(robot);
i++;
robot.delay(1000);
}
}
}
class TestThreadGroup extends ThreadGroup {
TestThreadGroup(ThreadGroup threadGroup, String name){
TestThreadGroup(ThreadGroup threadGroup, String name) {
super(threadGroup, name);
}
public void uncaughtException(Thread exitedThread, Throwable e) {
e.printStackTrace();
if ((e instanceof ExceptionInInitializerError) || (e instanceof
NoClassDefFoundError)){
throw new RuntimeException("Test failed: other Exceptions were thrown ", e);
public void uncaughtException(Thread thread, Throwable e) {
System.out.println("Exception caught: " + e);
e.printStackTrace(System.out);
System.out.flush();
if ((e instanceof ExceptionInInitializerError) ||
(e instanceof NoClassDefFoundError))
{
// These two are expected
return;
}
LoopRobustness.otherExceptionsCaught = true;
}
}
......
/*
* Copyright (c) 2010, 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
@test
@bug 6424157
@author Artem Ananiev: area=eventqueue
@run main PreserveDispatchThread
*/
import java.awt.*;
import java.awt.event.*;
public class PreserveDispatchThread {
private static volatile Frame f;
private static volatile Dialog d;
private static volatile boolean isEDT = true;
public static void main(String[] args) throws Exception {
f = new Frame("F");
f.setSize(320, 340);
f.setLocationRelativeTo(null);
f.setVisible(true);
try {
test1();
if (!isEDT) {
throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed");
}
test2();
if (!isEDT) {
throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed");
}
test3();
if (!isEDT) {
throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed");
}
} finally {
if (d != null) {
d.dispose();
}
f.dispose();
}
}
/*
* Tests that push/pop doesn't change the dispatch thread if
* called on EDT.
*/
private static void test1() throws Exception {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
TestEventQueue teq = new TestEventQueue();
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
try {
seq.push(teq);
d = new TestDialog();
d.setVisible(true);
checkEDT();
} finally {
teq.pop();
}
checkEDT();
}
});
}
/*
* Tests that push/pop doesn't change the dispatch thread if
* called on the main thread.
*/
private static void test2() throws Exception {
TestEventQueue teq = new TestEventQueue();
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
try {
seq.push(teq);
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
checkEDT();
d = new TestDialog();
d.setVisible(true);
checkEDT();
}
});
} finally {
teq.pop();
}
}
private static final Object test3Lock = new Object();
private static boolean test3Sync = false;
/*
* A complex test: several nested invokeLater() are called and
* in every runnable a check for EDT is performed. At the ent
* of the test we wait for all the runnables to be processed
* and the dialog is disposed; otherwise the last EDT check can
* be later than this method returns and the whole test is passed.
*/
private static void test3() throws Exception {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
d = new Dialog(f, true);
d.setSize(240, 180);
d.setLocationRelativeTo(f);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
d.setVisible(true);
checkEDT();
}
});
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
TestEventQueue teq = new TestEventQueue();
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
try {
seq.push(teq);
checkEDT();
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
d.dispose();
checkEDT();
synchronized (test3Lock) {
test3Sync = true;
test3Lock.notify();
}
}
});
} finally {
teq.pop();
}
checkEDT();
}
});
checkEDT();
}
});
synchronized (test3Lock) {
while (!test3Sync) {
try {
test3Lock.wait();
} catch (InterruptedException ie) {
break;
}
}
}
// Make sure all the nested invokeLater/invokeAndWait are processed
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
}
});
}
private static void checkEDT() {
isEDT = isEDT && EventQueue.isDispatchThread();
}
private static class TestEventQueue extends EventQueue {
public TestEventQueue() {
super();
}
public void pop() {
super.pop();
}
}
private static class TestDialog extends Dialog {
private volatile boolean dialogShown = false;
private volatile boolean paintCalled = false;
public TestDialog() {
super(f, true);
setSize(240, 180);
setLocationRelativeTo(f);
addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
if (paintCalled) {
dispose();
}
dialogShown = true;
}
});
}
@Override
public void paint(Graphics g) {
if (dialogShown) {
dispose();
}
paintCalled = true;
}
}
}
......@@ -43,6 +43,7 @@ public class PushPopTest {
Runnable dummy = new Runnable() {
public void run() {
System.err.println("Dummy is here.");
System.err.flush();
}
};
EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue();
......@@ -58,10 +59,11 @@ public class PushPopTest {
Runnable runnable = new Runnable() {
public void run() {
System.err.println("Dummy from SunToolkit");
System.err.flush();
}
};
InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false);
System.err.println(ie);
// System.err.println(ie);
SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie);
eq1.pop();
frame.dispose();
......@@ -70,14 +72,14 @@ public class PushPopTest {
class MyEventQueue1 extends EventQueue {
public void pop() throws EmptyStackException {
public void pop() {
super.pop();
}
}
class MyEventQueue2 extends EventQueue {
protected void pop() throws EmptyStackException {
protected void pop() {
System.err.println("pop2()");
Thread.dumpStack();
try {
......@@ -85,7 +87,8 @@ class MyEventQueue2 extends EventQueue {
public void run() {
Runnable runnable = new Runnable() {
public void run() {
System.err.println("Dummy from here");
System.err.println("Dummy from pop");
System.err.flush();
}
};
InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册