Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
b35e03fd
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
b35e03fd
编写于
8月 24, 2010
作者:
A
art
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6949936: Provide API for running nested events loops, similar to what modal dialogs do
Reviewed-by: ant, anthony
上级
4a65aa9b
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
629 addition
and
98 deletion
+629
-98
src/share/classes/java/awt/Dialog.java
src/share/classes/java/awt/Dialog.java
+15
-96
src/share/classes/java/awt/EventDispatchThread.java
src/share/classes/java/awt/EventDispatchThread.java
+4
-2
src/share/classes/java/awt/EventQueue.java
src/share/classes/java/awt/EventQueue.java
+35
-0
src/share/classes/java/awt/SecondaryLoop.java
src/share/classes/java/awt/SecondaryLoop.java
+147
-0
src/share/classes/java/awt/WaitDispatchSupport.java
src/share/classes/java/awt/WaitDispatchSupport.java
+302
-0
test/java/awt/EventQueue/SecondaryLoopTest/SecondaryLoopTest.java
...a/awt/EventQueue/SecondaryLoopTest/SecondaryLoopTest.java
+126
-0
未找到文件。
src/share/classes/java/awt/Dialog.java
浏览文件 @
b35e03fd
...
...
@@ -277,10 +277,8 @@ public class Dialog extends Window {
*/
String
title
;
private
transient
volatile
boolean
keepBlockingEDT
=
false
;
private
transient
volatile
boolean
keepBlockingCT
=
false
;
private
transient
ModalEventFilter
modalFilter
;
private
transient
volatile
SecondaryLoop
secondaryLoop
;
/*
* Indicates that this dialog is being hidden. This flag is set to true at
...
...
@@ -1005,12 +1003,6 @@ public class Dialog extends Window {
super
.
setVisible
(
b
);
}
/**
* Stores the app context on which event dispatch thread the dialog
* is being shown. Initialized in show(), used in hideAndDisposeHandler()
*/
transient
private
AppContext
showAppContext
;
/**
* Makes the {@code Dialog} visible. If the dialog and/or its owner
* are not yet displayable, both are made displayable. The
...
...
@@ -1037,39 +1029,18 @@ public class Dialog extends Window {
if
(!
isModal
())
{
conditionalShow
(
null
,
null
);
}
else
{
// Set this variable before calling conditionalShow(). That
// way, if the Dialog is hidden right after being shown, we
// won't mistakenly block this thread.
keepBlockingEDT
=
true
;
keepBlockingCT
=
true
;
// Store the app context on which this dialog is being shown.
// Event dispatch thread of this app context will be sleeping until
// we wake it by any event from hideAndDisposeHandler().
showAppContext
=
AppContext
.
getAppContext
();
AppContext
showAppContext
=
AppContext
.
getAppContext
();
AtomicLong
time
=
new
AtomicLong
();
Component
predictedFocusOwner
=
null
;
try
{
predictedFocusOwner
=
getMostRecentFocusOwner
();
if
(
conditionalShow
(
predictedFocusOwner
,
time
))
{
// We have two mechanisms for blocking: 1. If we're on the
// EventDispatchThread, start a new event pump. 2. If we're
// on any other thread, call wait() on the treelock.
modalFilter
=
ModalEventFilter
.
createFilterForDialog
(
this
);
final
Runnable
pumpEventsForFilter
=
new
Runnable
()
{
public
void
run
()
{
EventDispatchThread
dispatchThread
=
(
EventDispatchThread
)
Thread
.
currentThread
();
dispatchThread
.
pumpEventsForFilter
(
new
Conditional
()
{
public
boolean
evaluate
()
{
synchronized
(
getTreeLock
())
{
return
keepBlockingEDT
&&
windowClosingException
==
null
;
}
}
},
modalFilter
);
Conditional
cond
=
new
Conditional
()
{
@Override
public
boolean
evaluate
()
{
return
windowClosingException
==
null
;
}
};
...
...
@@ -1096,44 +1067,10 @@ public class Dialog extends Window {
modalityPushed
();
try
{
if
(
EventQueue
.
isDispatchThread
())
{
/*
* dispose SequencedEvent we are dispatching on current
* AppContext, to prevent us from hang.
*
*/
// BugId 4531693 (son@sparc.spb.su)
SequencedEvent
currentSequencedEvent
=
KeyboardFocusManager
.
getCurrentKeyboardFocusManager
().
getCurrentSequencedEvent
();
if
(
currentSequencedEvent
!=
null
)
{
currentSequencedEvent
.
dispose
();
}
/*
* Event processing is done inside doPrivileged block so that
* it wouldn't matter even if user code is on the stack
* Fix for BugId 6300270
*/
AccessController
.
doPrivileged
(
new
PrivilegedAction
()
{
public
Object
run
()
{
pumpEventsForFilter
.
run
();
return
null
;
}
});
}
else
{
synchronized
(
getTreeLock
())
{
Toolkit
.
getEventQueue
().
postEvent
(
new
PeerEvent
(
this
,
pumpEventsForFilter
,
PeerEvent
.
PRIORITY_EVENT
));
while
(
keepBlockingCT
&&
windowClosingException
==
null
)
{
try
{
getTreeLock
().
wait
();
}
catch
(
InterruptedException
e
)
{
break
;
}
}
}
EventQueue
eventQueue
=
Toolkit
.
getDefaultToolkit
().
getSystemEventQueue
();
secondaryLoop
=
eventQueue
.
createSecondaryLoop
(
cond
,
modalFilter
,
5000
);
if
(!
secondaryLoop
.
enter
())
{
secondaryLoop
=
null
;
}
}
finally
{
modalityPopped
();
...
...
@@ -1194,18 +1131,11 @@ public class Dialog extends Window {
windowClosingException
=
null
;
}
}
final
class
WakingRunnable
implements
Runnable
{
public
void
run
()
{
synchronized
(
getTreeLock
())
{
keepBlockingCT
=
false
;
getTreeLock
().
notifyAll
();
}
}
}
private
void
hideAndDisposePreHandler
()
{
isInHide
=
true
;
synchronized
(
getTreeLock
())
{
if
(
keepBlockingEDT
)
{
if
(
secondaryLoop
!=
null
)
{
modalHide
();
// dialog can be shown and then disposed before its
// modal filter is created
...
...
@@ -1217,20 +1147,9 @@ public class Dialog extends Window {
}
}
private
void
hideAndDisposeHandler
()
{
synchronized
(
getTreeLock
())
{
if
(
keepBlockingEDT
)
{
keepBlockingEDT
=
false
;
PeerEvent
wakingEvent
=
new
PeerEvent
(
getToolkit
(),
new
WakingRunnable
(),
PeerEvent
.
PRIORITY_EVENT
);
AppContext
curAppContext
=
AppContext
.
getAppContext
();
if
(
showAppContext
!=
curAppContext
)
{
// Wake up event dispatch thread on which the dialog was
// initially shown
SunToolkit
.
postEvent
(
showAppContext
,
wakingEvent
);
showAppContext
=
null
;
}
else
{
Toolkit
.
getEventQueue
().
postEvent
(
wakingEvent
);
}
}
if
(
secondaryLoop
!=
null
)
{
secondaryLoop
.
exit
();
secondaryLoop
=
null
;
}
isInHide
=
false
;
}
...
...
src/share/classes/java/awt/EventDispatchThread.java
浏览文件 @
b35e03fd
...
...
@@ -113,8 +113,7 @@ class EventDispatchThread extends Thread {
pumpEventsForHierarchy
(
id
,
cond
,
null
);
}
void
pumpEventsForHierarchy
(
int
id
,
Conditional
cond
,
Component
modalComponent
)
{
void
pumpEventsForHierarchy
(
int
id
,
Conditional
cond
,
Component
modalComponent
)
{
pumpEventsForFilter
(
id
,
cond
,
new
HierarchyEventFilter
(
modalComponent
));
}
...
...
@@ -124,6 +123,7 @@ class EventDispatchThread extends Thread {
void
pumpEventsForFilter
(
int
id
,
Conditional
cond
,
EventFilter
filter
)
{
addEventFilter
(
filter
);
doDispatch
=
true
;
while
(
doDispatch
&&
cond
.
evaluate
())
{
if
(
isInterrupted
()
||
!
pumpOneEventForFilters
(
id
))
{
doDispatch
=
false
;
...
...
@@ -133,6 +133,7 @@ class EventDispatchThread extends Thread {
}
void
addEventFilter
(
EventFilter
filter
)
{
eventLog
.
finest
(
"adding the event filter: "
+
filter
);
synchronized
(
eventFilters
)
{
if
(!
eventFilters
.
contains
(
filter
))
{
if
(
filter
instanceof
ModalEventFilter
)
{
...
...
@@ -156,6 +157,7 @@ class EventDispatchThread extends Thread {
}
void
removeEventFilter
(
EventFilter
filter
)
{
eventLog
.
finest
(
"removing the event filter: "
+
filter
);
synchronized
(
eventFilters
)
{
eventFilters
.
remove
(
filter
);
}
...
...
src/share/classes/java/awt/EventQueue.java
浏览文件 @
b35e03fd
...
...
@@ -883,6 +883,41 @@ public class EventQueue {
}
}
/**
* Creates a new {@code secondary loop} associated with this
* event queue. Use the {@link SecondaryLoop#enter} and
* {@link SecondaryLoop#exit} methods to start and stop the
* event loop and dispatch the events from this queue.
*
* @return secondaryLoop A new secondary loop object, which can
* be used to launch a new nested event
* loop and dispatch events from this queue
*
* @see SecondaryLoop#enter
* @see SecondaryLoop#exit
*
* @since 1.7
*/
public
SecondaryLoop
createSecondaryLoop
()
{
return
createSecondaryLoop
(
null
,
null
,
0
);
}
SecondaryLoop
createSecondaryLoop
(
Conditional
cond
,
EventFilter
filter
,
long
interval
)
{
pushPopLock
.
lock
();
try
{
if
(
nextQueue
!=
null
)
{
// Forward the request to the top of EventQueue stack
return
nextQueue
.
createSecondaryLoop
(
cond
,
filter
,
interval
);
}
if
(
dispatchThread
==
null
)
{
initDispatchThread
();
}
return
new
WaitDispatchSupport
(
dispatchThread
,
cond
,
filter
,
interval
);
}
finally
{
pushPopLock
.
unlock
();
}
}
/**
* Returns true if the calling thread is
* {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
...
...
src/share/classes/java/awt/SecondaryLoop.java
0 → 100644
浏览文件 @
b35e03fd
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package
java.awt
;
/**
* A helper interface to run the nested event loop.
* <p>
* Objects that implement this interface are created with the
* {@link EventQueue#createSecondaryLoop} method. The interface
* provides two methods, {@link enter} and {@link exit},
* which can be used to start and stop the event loop.
* <p>
* When the {@link enter} method is called, the current
* thread is blocked until the loop is terminated by the
* {@link exit} method. Also, a new event loop is started
* on the event dispatch thread, which may or may not be
* the current thread. The loop can be terminated on any
* thread by calling its {@link exit} method. After the
* loop is terminated, the {@code SecondaryLoop} object can
* be reused to run a new nested event loop.
* <p>
* A typical use case of applying this interface is AWT
* and Swing modal dialogs. When a modal dialog is shown on
* the event dispatch thread, it enters a new secondary loop.
* Later, when the dialog is hidden or disposed, it exits
* the loop, and the thread continues its execution.
* <p>
* The following example illustrates a simple use case of
* secondary loops:
*
* <pre>
* SecondaryLoop loop;
*
* JButton jButton = new JButton("Button");
* jButton.addActionListener(new ActionListener() {
* {@code @Override}
* public void actionPerformed(ActionEvent e) {
* Toolkit tk = Toolkit.getDefaultToolkit();
* EventQueue eq = tk.getSystemEventQueue();
* loop = eq.createSecondaryLoop();
*
* // Spawn a new thread to do the work
* Thread worker = new WorkerThread();
* worker.start();
*
* // Enter the loop to block the current event
* // handler, but leave UI responsive
* if (!loop.enter()) {
* // Report an error
* }
* }
* });
*
* class WorkerThread extends Thread {
* {@code @Override}
* public void run() {
* // Perform calculations
* doSomethingUseful();
*
* // Exit the loop
* loop.exit();
* }
* }
* </pre>
*
* @see Dialog#show
* @see EventQueue#createSecondaryLoop
* @see Toolkit#getSystemEventQueue
*
* @author Anton Tarasov, Artem Ananiev
*
* @since 1.7
*/
public
interface
SecondaryLoop
{
/**
* Blocks the execution of the current thread and enters a new
* secondary event loop on the event dispatch thread.
* <p>
* This method can be called by any thread including the event
* dispatch thread. This thread will be blocked until the {@link
* exit} method is called or the loop is terminated. A new
* secondary loop will be created on the event dispatch thread
* for dispatching events in either case.
* <p>
* This method can only start one new event loop at a time per
* object. If a secondary event loop has already been started
* by this object and is currently still running, this method
* returns {@code false} to indicate that it was not successful
* in starting a new event loop. Otherwise, this method blocks
* the calling thread and later returns {@code true} when the
* new event loop is terminated. At such time, this object can
* again be used to start another new event loop.
*
* @return {@code true} after termination of the secondary loop,
* if the secondary loop was started by this call,
* {@code false} otherwise
*/
public
boolean
enter
();
/**
* Unblocks the execution of the thread blocked by the {@link
* enter} method and exits the secondary loop.
* <p>
* This method resumes the thread that called the {@link enter}
* method and exits the secondary loop that was created when
* the {@link enter} method was invoked.
* <p>
* Note that if any other secondary loop is started while this
* loop is running, the blocked thread will not resume execution
* until the nested loop is terminated.
* <p>
* If this secondary loop has not been started with the {@link
* enter} method, or this secondary loop has already finished
* with the {@link exit} method, this method returns {@code
* false}, otherwise {@code true} is returned.
*
* @return {@code true} if this loop was previously started and
* has not yet been finished with the {@link exit} method,
* {@code false} otherwise
*/
public
boolean
exit
();
}
src/share/classes/java/awt/WaitDispatchSupport.java
0 → 100644
浏览文件 @
b35e03fd
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package
java.awt
;
import
java.util.Timer
;
import
java.util.TimerTask
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.security.PrivilegedAction
;
import
java.security.AccessController
;
import
sun.awt.PeerEvent
;
import
sun.util.logging.PlatformLogger
;
/**
* This utility class is used to suspend execution on a thread
* while still allowing {@code EventDispatchThread} to dispatch events.
* The API methods of the class are thread-safe.
*
* @author Anton Tarasov, Artem Ananiev
*
* @since 1.7
*/
class
WaitDispatchSupport
implements
SecondaryLoop
{
private
final
static
PlatformLogger
log
=
PlatformLogger
.
getLogger
(
"java.awt.event.WaitDispatchSupport"
);
private
EventDispatchThread
dispatchThread
;
private
EventFilter
filter
;
private
volatile
Conditional
extCondition
;
private
volatile
Conditional
condition
;
private
long
interval
;
// Use a shared daemon timer to serve all the WaitDispatchSupports
private
static
Timer
timer
;
// When this WDS expires, we cancel the timer task leaving the
// shared timer up and running
private
TimerTask
timerTask
;
private
AtomicBoolean
keepBlockingEDT
=
new
AtomicBoolean
(
false
);
private
AtomicBoolean
keepBlockingCT
=
new
AtomicBoolean
(
false
);
private
static
synchronized
void
initializeTimer
()
{
if
(
timer
==
null
)
{
timer
=
new
Timer
(
"AWT-WaitDispatchSupport-Timer"
,
true
);
}
}
/**
* Creates a {@code WaitDispatchSupport} instance to
* serve the given event dispatch thread.
*
* @param dispatchThread An event dispatch thread that
* should not stop dispatching events while waiting
*
* @since 1.7
*/
public
WaitDispatchSupport
(
EventDispatchThread
dispatchThread
)
{
this
(
dispatchThread
,
null
);
}
/**
* Creates a {@code WaitDispatchSupport} instance to
* serve the given event dispatch thread.
*
* @param dispatchThread An event dispatch thread that
* should not stop dispatching events while waiting
* @param extCondition A conditional object used to determine
* if the loop should be terminated
*
* @since 1.7
*/
public
WaitDispatchSupport
(
EventDispatchThread
dispatchThread
,
Conditional
extCond
)
{
if
(
dispatchThread
==
null
)
{
throw
new
IllegalArgumentException
(
"The dispatchThread can not be null"
);
}
this
.
dispatchThread
=
dispatchThread
;
this
.
extCondition
=
extCond
;
this
.
condition
=
new
Conditional
()
{
@Override
public
boolean
evaluate
()
{
if
(
log
.
isLoggable
(
PlatformLogger
.
FINEST
))
{
log
.
finest
(
"evaluate(): blockingEDT="
+
keepBlockingEDT
.
get
()
+
", blockingCT="
+
keepBlockingCT
.
get
());
}
boolean
extEvaluate
=
(
extCondition
!=
null
)
?
extCondition
.
evaluate
()
:
true
;
if
(!
keepBlockingEDT
.
get
()
||
!
extEvaluate
)
{
if
(
timerTask
!=
null
)
{
timerTask
.
cancel
();
timerTask
=
null
;
}
return
false
;
}
return
true
;
}
};
}
/**
* Creates a {@code WaitDispatchSupport} instance to
* serve the given event dispatch thread.
* <p>
* The {@link EventFilter} is set on the {@code dispatchThread}
* while waiting. The filter is removed on completion of the
* waiting process.
* <p>
*
*
* @param dispatchThread An event dispatch thread that
* should not stop dispatching events while waiting
* @param filter {@code EventFilter} to be set
* @param interval A time interval to wait for. Note that
* when the waiting process takes place on EDT
* there is no guarantee to stop it in the given time
*
* @since 1.7
*/
public
WaitDispatchSupport
(
EventDispatchThread
dispatchThread
,
Conditional
extCondition
,
EventFilter
filter
,
long
interval
)
{
this
(
dispatchThread
,
extCondition
);
this
.
filter
=
filter
;
if
(
interval
<
0
)
{
throw
new
IllegalArgumentException
(
"The interval value must be >= 0"
);
}
this
.
interval
=
interval
;
if
(
interval
!=
0
)
{
initializeTimer
();
}
}
/**
* @inheritDoc
*/
@Override
public
boolean
enter
()
{
log
.
fine
(
"enter(): blockingEDT="
+
keepBlockingEDT
.
get
()
+
", blockingCT="
+
keepBlockingCT
.
get
());
if
(!
keepBlockingEDT
.
compareAndSet
(
false
,
true
))
{
log
.
fine
(
"The secondary loop is already running, aborting"
);
return
false
;
}
final
Runnable
run
=
new
Runnable
()
{
public
void
run
()
{
log
.
fine
(
"Starting a new event pump"
);
if
(
filter
==
null
)
{
dispatchThread
.
pumpEvents
(
condition
);
}
else
{
dispatchThread
.
pumpEventsForFilter
(
condition
,
filter
);
}
}
};
// We have two mechanisms for blocking: if we're on the
// dispatch thread, start a new event pump; if we're
// on any other thread, call wait() on the treelock
Thread
currentThread
=
Thread
.
currentThread
();
if
(
currentThread
==
dispatchThread
)
{
log
.
finest
(
"On dispatch thread: "
+
dispatchThread
);
if
(
interval
!=
0
)
{
log
.
finest
(
"scheduling the timer for "
+
interval
+
" ms"
);
timer
.
schedule
(
timerTask
=
new
TimerTask
()
{
@Override
public
void
run
()
{
if
(
keepBlockingEDT
.
compareAndSet
(
true
,
false
))
{
wakeupEDT
();
}
}
},
interval
);
}
// Dispose SequencedEvent we are dispatching on the the current
// AppContext, to prevent us from hang - see 4531693 for details
SequencedEvent
currentSE
=
KeyboardFocusManager
.
getCurrentKeyboardFocusManager
().
getCurrentSequencedEvent
();
if
(
currentSE
!=
null
)
{
log
.
fine
(
"Dispose current SequencedEvent: "
+
currentSE
);
currentSE
.
dispose
();
}
// In case the exit() method is called before starting
// new event pump it will post the waking event to EDT.
// The event will be handled after the the new event pump
// starts. Thus, the enter() method will not hang.
//
// Event pump should be privileged. See 6300270.
AccessController
.
doPrivileged
(
new
PrivilegedAction
()
{
public
Object
run
()
{
run
.
run
();
return
null
;
}
});
}
else
{
log
.
finest
(
"On non-dispatch thread: "
+
currentThread
);
synchronized
(
getTreeLock
())
{
if
(
filter
!=
null
)
{
dispatchThread
.
addEventFilter
(
filter
);
}
try
{
EventQueue
eq
=
dispatchThread
.
getEventQueue
();
eq
.
postEvent
(
new
PeerEvent
(
this
,
run
,
PeerEvent
.
PRIORITY_EVENT
));
keepBlockingCT
.
set
(
true
);
if
(
interval
>
0
)
{
long
currTime
=
System
.
currentTimeMillis
();
while
(
keepBlockingCT
.
get
()
&&
((
extCondition
!=
null
)
?
extCondition
.
evaluate
()
:
true
)
&&
(
currTime
+
interval
>
System
.
currentTimeMillis
()))
{
getTreeLock
().
wait
(
interval
);
}
}
else
{
while
(
keepBlockingCT
.
get
()
&&
((
extCondition
!=
null
)
?
extCondition
.
evaluate
()
:
true
))
{
getTreeLock
().
wait
();
}
}
log
.
fine
(
"waitDone "
+
keepBlockingEDT
.
get
()
+
" "
+
keepBlockingCT
.
get
());
}
catch
(
InterruptedException
e
)
{
log
.
fine
(
"Exception caught while waiting: "
+
e
);
}
finally
{
if
(
filter
!=
null
)
{
dispatchThread
.
removeEventFilter
(
filter
);
}
}
// If the waiting process has been stopped because of the
// time interval passed or an exception occurred, the state
// should be changed
keepBlockingEDT
.
set
(
false
);
keepBlockingCT
.
set
(
false
);
}
}
return
true
;
}
/**
* @inheritDoc
*/
public
boolean
exit
()
{
log
.
fine
(
"exit(): blockingEDT="
+
keepBlockingEDT
.
get
()
+
", blockingCT="
+
keepBlockingCT
.
get
());
if
(
keepBlockingEDT
.
compareAndSet
(
true
,
false
))
{
wakeupEDT
();
return
true
;
}
return
false
;
}
private
final
static
Object
getTreeLock
()
{
return
Component
.
LOCK
;
}
private
final
Runnable
wakingRunnable
=
new
Runnable
()
{
public
void
run
()
{
log
.
fine
(
"Wake up EDT"
);
synchronized
(
getTreeLock
())
{
keepBlockingCT
.
set
(
false
);
getTreeLock
().
notifyAll
();
}
log
.
fine
(
"Wake up EDT done"
);
}
};
private
void
wakeupEDT
()
{
log
.
finest
(
"wakeupEDT(): EDT == "
+
dispatchThread
);
EventQueue
eq
=
dispatchThread
.
getEventQueue
();
eq
.
postEvent
(
new
PeerEvent
(
this
,
wakingRunnable
,
PeerEvent
.
PRIORITY_EVENT
));
}
}
test/java/awt/EventQueue/SecondaryLoopTest/SecondaryLoopTest.java
0 → 100644
浏览文件 @
b35e03fd
/*
* 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 6949936
@author Artem Ananiev: area=eventqueue
@run main/timeout=30 SecondaryLoopTest
*/
import
java.awt.*
;
/**
* Unit test for java.awt.SecondaryLoop implementation
*/
public
class
SecondaryLoopTest
{
private
static
volatile
boolean
loopStarted
;
private
static
volatile
boolean
doubleEntered
;
private
static
volatile
boolean
loopActive
;
private
static
volatile
boolean
eventDispatched
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
test
(
true
,
true
);
test
(
true
,
false
);
test
(
false
,
true
);
test
(
false
,
false
);
}
private
static
void
test
(
final
boolean
enterEDT
,
final
boolean
exitEDT
)
throws
Exception
{
System
.
out
.
println
(
"Running test("
+
enterEDT
+
", "
+
exitEDT
+
")"
);
System
.
err
.
flush
();
loopStarted
=
true
;
Runnable
enterRun
=
new
Runnable
()
{
@Override
public
void
run
()
{
Toolkit
tk
=
Toolkit
.
getDefaultToolkit
();
EventQueue
eq
=
tk
.
getSystemEventQueue
();
final
SecondaryLoop
loop
=
eq
.
createSecondaryLoop
();
doubleEntered
=
false
;
eventDispatched
=
false
;
Runnable
eventRun
=
new
Runnable
()
{
@Override
public
void
run
()
{
// Let the loop enter
sleep
(
1000
);
if
(
loop
.
enter
())
{
doubleEntered
=
true
;
}
eventDispatched
=
true
;
}
};
EventQueue
.
invokeLater
(
eventRun
);
Runnable
exitRun
=
new
Runnable
()
{
@Override
public
void
run
()
{
// Let the loop enter and eventRun finish
sleep
(
2000
);
if
(
doubleEntered
)
{
// Hopefully, we get here if the loop is entered twice
loop
.
exit
();
}
loop
.
exit
();
}
};
if
(
exitEDT
)
{
EventQueue
.
invokeLater
(
exitRun
);
}
else
{
new
Thread
(
exitRun
).
start
();
}
if
(!
loop
.
enter
())
{
loopStarted
=
false
;
}
loopActive
=
eventDispatched
;
}
};
if
(
enterEDT
)
{
EventQueue
.
invokeAndWait
(
enterRun
);
}
else
{
enterRun
.
run
();
}
// Print all the flags before we fail with exception
System
.
out
.
println
(
" loopStarted = "
+
loopStarted
);
System
.
out
.
println
(
" doubleEntered = "
+
doubleEntered
);
System
.
out
.
println
(
" loopActive = "
+
loopActive
);
System
.
out
.
flush
();
if
(!
loopStarted
)
{
throw
new
RuntimeException
(
"Test FAILED: the secondary loop is not started"
);
}
if
(
doubleEntered
)
{
throw
new
RuntimeException
(
"Test FAILED: the secondary loop is started twice"
);
}
if
(!
loopActive
)
{
throw
new
RuntimeException
(
"Test FAILED: the secondary loop exited immediately"
);
}
}
private
static
void
sleep
(
long
t
)
{
try
{
Thread
.
sleep
(
t
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
(
System
.
err
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录