Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
a978f8f4
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看板
提交
a978f8f4
编写于
11月 27, 2009
作者:
A
art
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
4913324: Deadlock when using two event queues
Reviewed-by: anthony, ant, dcherepanov
上级
b3196ad1
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
359 addition
and
165 deletion
+359
-165
src/share/classes/java/awt/EventDispatchThread.java
src/share/classes/java/awt/EventDispatchThread.java
+3
-34
src/share/classes/java/awt/EventQueue.java
src/share/classes/java/awt/EventQueue.java
+230
-119
src/share/classes/sun/awt/AWTAccessor.java
src/share/classes/sun/awt/AWTAccessor.java
+4
-4
src/share/classes/sun/awt/AppContext.java
src/share/classes/sun/awt/AppContext.java
+18
-1
src/share/classes/sun/awt/SunToolkit.java
src/share/classes/sun/awt/SunToolkit.java
+1
-7
test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java
test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java
+103
-0
未找到文件。
src/share/classes/java/awt/EventDispatchThread.java
浏览文件 @
a978f8f4
...
...
@@ -104,11 +104,8 @@ class EventDispatchThread extends Thread {
}
else
{
stopEvent
.
dispatch
();
}
synchronized
(
theQueue
)
{
if
(
theQueue
.
getDispatchThread
()
==
this
)
{
theQueue
.
detachDispatchThread
();
}
}
theQueue
.
detachDispatchThread
(
this
,
false
);
}
public
void
stopDispatching
()
{
...
...
@@ -142,35 +139,7 @@ class EventDispatchThread extends Thread {
}
});
}
finally
{
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
* associated event queue. It is important because we notify
* that the event dispatch thread is busy after posting a new event
* to its queue, so the EventQueue.dispatchThread reference must
* be valid at that point.
*/
synchronized
(
theQueue
)
{
if
(
theQueue
.
getDispatchThread
()
==
this
)
{
theQueue
.
detachDispatchThread
();
}
/*
* 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.
*/
/*
* Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue.
*/
if
(
theQueue
.
peekEvent
()
!=
null
||
!
SunToolkit
.
isPostEventQueueEmpty
())
{
theQueue
.
initDispatchThread
();
}
AWTAutoShutdown
.
getInstance
().
notifyThreadFree
(
this
);
}
theQueue
.
detachDispatchThread
(
this
,
true
);
}
}
...
...
src/share/classes/java/awt/EventQueue.java
浏览文件 @
a978f8f4
...
...
@@ -45,6 +45,9 @@ import sun.awt.SunToolkit;
import
sun.awt.EventQueueItem
;
import
sun.awt.AWTAccessor
;
import
java.util.concurrent.locks.Condition
;
import
java.util.concurrent.locks.Lock
;
/**
* <code>EventQueue</code> is a platform-independent class
* that queues events, both from the underlying peer classes
...
...
@@ -127,6 +130,14 @@ public class EventQueue {
*/
private
EventQueue
previousQueue
;
/*
* A single lock to synchronize the push()/pop() and related operations with
* all the EventQueues from the AppContext. Synchronization on any particular
* event queue(s) is not enough: we should lock the whole stack.
*/
private
final
Lock
pushPopLock
;
private
final
Condition
pushPopCond
;
private
EventDispatchThread
dispatchThread
;
private
final
ThreadGroup
threadGroup
=
...
...
@@ -158,11 +169,11 @@ public class EventQueue {
static
{
AWTAccessor
.
setEventQueueAccessor
(
new
AWTAccessor
.
EventQueueAccessor
()
{
public
EventQueue
getNextQueue
(
EventQueue
eventQueue
)
{
return
eventQueue
.
nextQueue
;
}
public
Thread
getDispatchThread
(
EventQueue
eventQueue
)
{
return
eventQueue
.
dispatchThread
;
return
eventQueue
.
getDispatchThread
();
}
public
boolean
isDispatchThreadImpl
(
EventQueue
eventQueue
)
{
return
eventQueue
.
isDispatchThreadImpl
();
}
});
}
...
...
@@ -179,6 +190,9 @@ public class EventQueue {
* may call AppContext.getAppContext() before createNewAppContext()
* completes thus causing mess in thread group to appcontext mapping.
*/
pushPopLock
=
(
Lock
)
AppContext
.
getAppContext
().
get
(
AppContext
.
EVENT_QUEUE_LOCK_KEY
);
pushPopCond
=
(
Condition
)
AppContext
.
getAppContext
().
get
(
AppContext
.
EVENT_QUEUE_COND_KEY
);
}
/**
...
...
@@ -207,7 +221,8 @@ public class EventQueue {
*/
final
void
postEventPrivate
(
AWTEvent
theEvent
)
{
theEvent
.
isPosted
=
true
;
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
if
(
dispatchThread
==
null
&&
nextQueue
==
null
)
{
if
(
theEvent
.
getSource
()
==
AWTAutoShutdown
.
getInstance
())
{
return
;
...
...
@@ -221,6 +236,8 @@ public class EventQueue {
return
;
}
postEvent
(
theEvent
,
getPriority
(
theEvent
));
}
finally
{
pushPopLock
.
unlock
();
}
}
...
...
@@ -280,9 +297,9 @@ public class EventQueue {
if
(
theEvent
.
getSource
()
!=
AWTAutoShutdown
.
getInstance
())
{
AWTAutoShutdown
.
getInstance
().
notifyThreadBusy
(
dispatchThread
);
}
notify
All
();
pushPopCond
.
signal
All
();
}
else
if
(
notifyID
)
{
notify
All
();
pushPopCond
.
signal
All
();
}
}
else
{
// The event was not coalesced or has non-Component source.
...
...
@@ -290,7 +307,7 @@ public class EventQueue {
queues
[
priority
].
tail
.
next
=
newItem
;
queues
[
priority
].
tail
=
newItem
;
if
(
notifyID
)
{
notify
All
();
pushPopCond
.
signal
All
();
}
}
}
...
...
@@ -482,7 +499,8 @@ public class EventQueue {
* event queues are nested with push()/pop().
*/
SunToolkit
.
flushPendingEvents
();
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
for
(
int
i
=
NUM_PRIORITIES
-
1
;
i
>=
0
;
i
--)
{
if
(
queues
[
i
].
head
!=
null
)
{
EventQueueItem
entry
=
queues
[
i
].
head
;
...
...
@@ -495,7 +513,9 @@ public class EventQueue {
}
}
AWTAutoShutdown
.
getInstance
().
notifyThreadFree
(
dispatchThread
);
wait
();
pushPopCond
.
await
();
}
finally
{
pushPopLock
.
unlock
();
}
}
while
(
true
);
}
...
...
@@ -508,7 +528,8 @@ public class EventQueue {
* event queues are nested with push()/pop().
*/
SunToolkit
.
flushPendingEvents
();
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
for
(
int
i
=
0
;
i
<
NUM_PRIORITIES
;
i
++)
{
for
(
EventQueueItem
entry
=
queues
[
i
].
head
,
prev
=
null
;
entry
!=
null
;
prev
=
entry
,
entry
=
entry
.
next
)
...
...
@@ -527,9 +548,11 @@ public class EventQueue {
}
}
}
this
.
waitForID
=
id
;
wait
();
this
.
waitForID
=
0
;
waitForID
=
id
;
pushPopCond
.
await
();
waitForID
=
0
;
}
finally
{
pushPopLock
.
unlock
();
}
}
while
(
true
);
}
...
...
@@ -539,11 +562,16 @@ public class EventQueue {
* without removing it.
* @return the first event
*/
public
synchronized
AWTEvent
peekEvent
()
{
for
(
int
i
=
NUM_PRIORITIES
-
1
;
i
>=
0
;
i
--)
{
if
(
queues
[
i
].
head
!=
null
)
{
return
queues
[
i
].
head
.
event
;
public
AWTEvent
peekEvent
()
{
pushPopLock
.
lock
();
try
{
for
(
int
i
=
NUM_PRIORITIES
-
1
;
i
>=
0
;
i
--)
{
if
(
queues
[
i
].
head
!=
null
)
{
return
queues
[
i
].
head
.
event
;
}
}
}
finally
{
pushPopLock
.
unlock
();
}
return
null
;
...
...
@@ -555,14 +583,19 @@ public class EventQueue {
* @return the first event of the specified id or <code>null</code>
* if there is no such event
*/
public
synchronized
AWTEvent
peekEvent
(
int
id
)
{
for
(
int
i
=
NUM_PRIORITIES
-
1
;
i
>=
0
;
i
--)
{
EventQueueItem
q
=
queues
[
i
].
head
;
for
(;
q
!=
null
;
q
=
q
.
next
)
{
if
(
q
.
event
.
getID
()
==
id
)
{
return
q
.
event
;
public
AWTEvent
peekEvent
(
int
id
)
{
pushPopLock
.
lock
();
try
{
for
(
int
i
=
NUM_PRIORITIES
-
1
;
i
>=
0
;
i
--)
{
EventQueueItem
q
=
queues
[
i
].
head
;
for
(;
q
!=
null
;
q
=
q
.
next
)
{
if
(
q
.
event
.
getID
()
==
id
)
{
return
q
.
event
;
}
}
}
}
finally
{
pushPopLock
.
unlock
();
}
return
null
;
...
...
@@ -661,17 +694,27 @@ public class EventQueue {
public
static
long
getMostRecentEventTime
()
{
return
Toolkit
.
getEventQueue
().
getMostRecentEventTimeImpl
();
}
private
synchronized
long
getMostRecentEventTimeImpl
()
{
return
(
Thread
.
currentThread
()
==
dispatchThread
)
?
mostRecentEventTime
:
System
.
currentTimeMillis
();
private
long
getMostRecentEventTimeImpl
()
{
pushPopLock
.
lock
();
try
{
return
(
Thread
.
currentThread
()
==
dispatchThread
)
?
mostRecentEventTime
:
System
.
currentTimeMillis
();
}
finally
{
pushPopLock
.
unlock
();
}
}
/**
* @return most recent event time on all threads.
*/
synchronized
long
getMostRecentEventTimeEx
()
{
return
mostRecentEventTime
;
long
getMostRecentEventTimeEx
()
{
pushPopLock
.
lock
();
try
{
return
mostRecentEventTime
;
}
finally
{
pushPopLock
.
unlock
();
}
}
/**
...
...
@@ -689,10 +732,15 @@ public class EventQueue {
public
static
AWTEvent
getCurrentEvent
()
{
return
Toolkit
.
getEventQueue
().
getCurrentEventImpl
();
}
private
synchronized
AWTEvent
getCurrentEventImpl
()
{
return
(
Thread
.
currentThread
()
==
dispatchThread
)
?
((
AWTEvent
)
currentEvent
.
get
())
:
null
;
private
AWTEvent
getCurrentEventImpl
()
{
pushPopLock
.
lock
();
try
{
return
(
Thread
.
currentThread
()
==
dispatchThread
)
?
((
AWTEvent
)
currentEvent
.
get
())
:
null
;
}
finally
{
pushPopLock
.
unlock
();
}
}
/**
...
...
@@ -706,21 +754,22 @@ public class EventQueue {
* @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
* @since 1.2
*/
public
synchronized
void
push
(
EventQueue
newEventQueue
)
{
public
void
push
(
EventQueue
newEventQueue
)
{
if
(
eventLog
.
isLoggable
(
PlatformLogger
.
FINE
))
{
eventLog
.
fine
(
"EventQueue.push("
+
newEventQueue
+
")"
);
}
if
(
nextQueue
!=
null
)
{
nextQueue
.
push
(
newEventQueue
);
return
;
}
pushPopLock
.
lock
();
try
{
EventQueue
toPush
=
this
;
while
(
toPush
.
nextQueue
!=
null
)
{
toPush
=
toPush
.
nextQueue
;
}
synchronized
(
newEventQueue
)
{
// Transfer all events forward to new EventQueue.
while
(
peekEvent
()
!=
null
)
{
while
(
toPush
.
peekEvent
()
!=
null
)
{
try
{
newEventQueue
.
postEventPrivate
(
getNextEvent
());
newEventQueue
.
postEventPrivate
(
toPush
.
getNextEvent
());
}
catch
(
InterruptedException
ie
)
{
if
(
eventLog
.
isLoggable
(
PlatformLogger
.
FINE
))
{
eventLog
.
fine
(
"Interrupted push"
,
ie
);
...
...
@@ -728,27 +777,30 @@ public class EventQueue {
}
}
newEventQueue
.
previousQueue
=
t
his
;
}
/*
* 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, so if the dispatch
* thread attempts to synchronize on this EventQueue object
* it will never exit since we already hold this lock
.
*/
if
(
dispatchThread
!=
null
)
{
dispatchThread
.
stopDispatchingLater
();
}
newEventQueue
.
previousQueue
=
t
oPush
;
/*
* 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
();
}
nextQueue
=
newEventQueue
;
toPush
.
nextQueue
=
newEventQueue
;
AppContext
appContext
=
AppContext
.
getAppContext
();
if
(
appContext
.
get
(
AppContext
.
EVENT_QUEUE_KEY
)
==
this
)
{
appContext
.
put
(
AppContext
.
EVENT_QUEUE_KEY
,
newEventQueue
);
AppContext
appContext
=
AppContext
.
getAppContext
();
if
(
appContext
.
get
(
AppContext
.
EVENT_QUEUE_KEY
)
==
toPush
)
{
appContext
.
put
(
AppContext
.
EVENT_QUEUE_KEY
,
newEventQueue
);
}
}
finally
{
pushPopLock
.
unlock
();
}
}
...
...
@@ -770,25 +822,24 @@ public class EventQueue {
eventLog
.
fine
(
"EventQueue.pop("
+
this
+
")"
);
}
// To prevent deadlock, we lock on the previous EventQueue before
// this one. This uses the same locking order as everything else
// in EventQueue.java, so deadlock isn't possible.
EventQueue
prev
=
previousQueue
;
synchronized
((
prev
!=
null
)
?
prev
:
this
)
{
synchronized
(
this
)
{
if
(
nextQueue
!=
null
)
{
nextQueue
.
pop
();
return
;
EventDispatchThread
dt
=
null
;
pushPopLock
.
lock
();
try
{
EventQueue
toPop
=
this
;
while
(
toPop
.
nextQueue
!=
null
)
{
toPop
=
toPop
.
nextQueue
;
}
if
(
previousQueue
==
null
)
{
EventQueue
prev
=
toPop
.
previousQueue
;
if
(
prev
==
null
)
{
throw
new
EmptyStackException
();
}
toPop
.
previousQueue
=
null
;
// Transfer all events back to previous EventQueue.
prev
iousQueue
.
nextQueue
=
null
;
while
(
peekEvent
()
!=
null
)
{
prev
.
nextQueue
=
null
;
while
(
toPop
.
peekEvent
()
!=
null
)
{
try
{
prev
iousQueue
.
postEventPrivate
(
getNextEvent
());
prev
.
postEventPrivate
(
toPop
.
getNextEvent
());
}
catch
(
InterruptedException
ie
)
{
if
(
eventLog
.
isLoggable
(
PlatformLogger
.
FINE
))
{
eventLog
.
fine
(
"Interrupted pop"
,
ie
);
...
...
@@ -797,14 +848,14 @@ public class EventQueue {
}
AppContext
appContext
=
AppContext
.
getAppContext
();
if
(
appContext
.
get
(
AppContext
.
EVENT_QUEUE_KEY
)
==
this
)
{
appContext
.
put
(
AppContext
.
EVENT_QUEUE_KEY
,
prev
iousQueue
);
appContext
.
put
(
AppContext
.
EVENT_QUEUE_KEY
,
prev
);
}
previousQueue
=
null
;
}
dt
=
toPop
.
dispatchThread
;
}
finally
{
pushPopLock
.
unlock
();
}
EventDispatchThread
dt
=
this
.
dispatchThread
;
if
(
dt
!=
null
)
{
dt
.
stopDispatching
();
// Must be done outside synchronized
// block to avoid possible deadlock
...
...
@@ -833,16 +884,27 @@ public class EventQueue {
*/
public
static
boolean
isDispatchThread
()
{
EventQueue
eq
=
Toolkit
.
getEventQueue
();
EventQueue
next
=
eq
.
nextQueue
;
while
(
next
!=
null
)
{
eq
=
next
;
next
=
eq
.
nextQueue
;
return
eq
.
isDispatchThreadImpl
();
}
final
boolean
isDispatchThreadImpl
()
{
EventQueue
eq
=
this
;
pushPopLock
.
lock
();
try
{
EventQueue
next
=
eq
.
nextQueue
;
while
(
next
!=
null
)
{
eq
=
next
;
next
=
eq
.
nextQueue
;
}
return
(
Thread
.
currentThread
()
==
eq
.
dispatchThread
);
}
finally
{
pushPopLock
.
unlock
();
}
return
(
Thread
.
currentThread
()
==
eq
.
dispatchThread
);
}
final
void
initDispatchThread
()
{
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
AppContext
appContext
=
AppContext
.
getAppContext
();
if
(
dispatchThread
==
null
&&
!
threadGroup
.
isDestroyed
()
&&
!
appContext
.
isDisposed
())
{
dispatchThread
=
(
EventDispatchThread
)
...
...
@@ -861,11 +923,45 @@ public class EventQueue {
AWTAutoShutdown
.
getInstance
().
notifyThreadBusy
(
dispatchThread
);
dispatchThread
.
start
();
}
}
finally
{
pushPopLock
.
unlock
();
}
}
final
void
detachDispatchThread
()
{
dispatchThread
=
null
;
final
void
detachDispatchThread
(
EventDispatchThread
edt
,
boolean
restart
)
{
/*
* This synchronized block is to secure that the event dispatch
* thread won't die in the middle of posting a new event to the
* associated event queue. It is important because we notify
* that the event dispatch thread is busy after posting a new event
* to its queue, so the EventQueue.dispatchThread reference must
* be valid at that point.
*/
pushPopLock
.
lock
();
try
{
EventDispatchThread
oldDispatchThread
=
dispatchThread
;
if
(
dispatchThread
==
edt
)
{
dispatchThread
=
null
;
}
if
(
restart
)
{
/*
* 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.
*
* Fix for 4648733. Check both the associated java event
* queue and the PostEventQueue.
*/
if
((
peekEvent
()
!=
null
)
||
!
SunToolkit
.
isPostEventQueueEmpty
())
{
initDispatchThread
();
}
AWTAutoShutdown
.
getInstance
().
notifyThreadFree
(
oldDispatchThread
);
}
}
finally
{
pushPopLock
.
unlock
();
}
}
/*
...
...
@@ -878,7 +974,12 @@ public class EventQueue {
* @see java.awt.EventQueue#detachDispatchThread
*/
final
EventDispatchThread
getDispatchThread
()
{
return
dispatchThread
;
pushPopLock
.
lock
();
try
{
return
dispatchThread
;
}
finally
{
pushPopLock
.
unlock
();
}
}
/*
...
...
@@ -895,7 +996,8 @@ public class EventQueue {
*/
final
void
removeSourceEvents
(
Object
source
,
boolean
removeAllEvents
)
{
SunToolkit
.
flushPendingEvents
();
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
for
(
int
i
=
0
;
i
<
NUM_PRIORITIES
;
i
++)
{
EventQueueItem
entry
=
queues
[
i
].
head
;
EventQueueItem
prev
=
null
;
...
...
@@ -928,43 +1030,49 @@ public class EventQueue {
}
queues
[
i
].
tail
=
prev
;
}
}
finally
{
pushPopLock
.
unlock
();
}
}
static
void
setCurrentEventAndMostRecentTime
(
AWTEvent
e
)
{
Toolkit
.
getEventQueue
().
setCurrentEventAndMostRecentTimeImpl
(
e
);
}
private
synchronized
void
setCurrentEventAndMostRecentTimeImpl
(
AWTEvent
e
)
{
if
(
Thread
.
currentThread
()
!=
dispatchThread
)
{
return
;
}
private
void
setCurrentEventAndMostRecentTimeImpl
(
AWTEvent
e
)
{
pushPopLock
.
lock
();
try
{
if
(
Thread
.
currentThread
()
!=
dispatchThread
)
{
return
;
}
currentEvent
=
new
WeakReference
(
e
);
// This series of 'instanceof' checks should be replaced with a
// polymorphic type (for example, an interface which declares a
// getWhen() method). However, this would require us to make such
// a type public, or to place it in sun.awt. Both of these approaches
// have been frowned upon. So for now, we hack.
//
// In tiger, we will probably give timestamps to all events, so this
// will no longer be an issue.
long
mostRecentEventTime2
=
Long
.
MIN_VALUE
;
if
(
e
instanceof
InputEvent
)
{
InputEvent
ie
=
(
InputEvent
)
e
;
mostRecentEventTime2
=
ie
.
getWhen
();
}
else
if
(
e
instanceof
InputMethodEvent
)
{
InputMethodEvent
ime
=
(
InputMethodEvent
)
e
;
mostRecentEventTime2
=
ime
.
getWhen
();
}
else
if
(
e
instanceof
ActionEvent
)
{
ActionEvent
ae
=
(
ActionEvent
)
e
;
mostRecentEventTime2
=
ae
.
getWhen
();
}
else
if
(
e
instanceof
InvocationEvent
)
{
InvocationEvent
ie
=
(
InvocationEvent
)
e
;
mostRecentEventTime2
=
ie
.
getWhen
();
currentEvent
=
new
WeakReference
(
e
);
// This series of 'instanceof' checks should be replaced with a
// polymorphic type (for example, an interface which declares a
// getWhen() method). However, this would require us to make such
// a type public, or to place it in sun.awt. Both of these approaches
// have been frowned upon. So for now, we hack.
//
// In tiger, we will probably give timestamps to all events, so this
// will no longer be an issue.
long
mostRecentEventTime2
=
Long
.
MIN_VALUE
;
if
(
e
instanceof
InputEvent
)
{
InputEvent
ie
=
(
InputEvent
)
e
;
mostRecentEventTime2
=
ie
.
getWhen
();
}
else
if
(
e
instanceof
InputMethodEvent
)
{
InputMethodEvent
ime
=
(
InputMethodEvent
)
e
;
mostRecentEventTime2
=
ime
.
getWhen
();
}
else
if
(
e
instanceof
ActionEvent
)
{
ActionEvent
ae
=
(
ActionEvent
)
e
;
mostRecentEventTime2
=
ae
.
getWhen
();
}
else
if
(
e
instanceof
InvocationEvent
)
{
InvocationEvent
ie
=
(
InvocationEvent
)
e
;
mostRecentEventTime2
=
ie
.
getWhen
();
}
mostRecentEventTime
=
Math
.
max
(
mostRecentEventTime
,
mostRecentEventTime2
);
}
finally
{
pushPopLock
.
unlock
();
}
mostRecentEventTime
=
Math
.
max
(
mostRecentEventTime
,
mostRecentEventTime2
);
}
/**
...
...
@@ -1045,15 +1153,18 @@ public class EventQueue {
* or starts a new one otherwise.
*/
private
void
wakeup
(
boolean
isShutdown
)
{
synchronized
(
this
)
{
pushPopLock
.
lock
();
try
{
if
(
nextQueue
!=
null
)
{
// Forward call to the top of EventQueue stack.
nextQueue
.
wakeup
(
isShutdown
);
}
else
if
(
dispatchThread
!=
null
)
{
notify
All
();
pushPopCond
.
signal
All
();
}
else
if
(!
isShutdown
)
{
initDispatchThread
();
}
}
finally
{
pushPopLock
.
unlock
();
}
}
}
...
...
src/share/classes/sun/awt/AWTAccessor.java
浏览文件 @
a978f8f4
...
...
@@ -248,14 +248,14 @@ public final class AWTAccessor {
* An accessor for the EventQueue class
*/
public
interface
EventQueueAccessor
{
/*
* Gets the next event queue.
*/
EventQueue
getNextQueue
(
EventQueue
eventQueue
);
/*
* Gets the event dispatch thread.
*/
Thread
getDispatchThread
(
EventQueue
eventQueue
);
/*
* Checks if the current thread is EDT for the given EQ.
*/
public
boolean
isDispatchThreadImpl
(
EventQueue
eventQueue
);
}
/*
...
...
src/share/classes/sun/awt/AppContext.java
浏览文件 @
a978f8f4
...
...
@@ -43,6 +43,9 @@ import java.util.HashSet;
import
java.beans.PropertyChangeSupport
;
import
java.beans.PropertyChangeListener
;
import
sun.util.logging.PlatformLogger
;
import
java.util.concurrent.locks.Condition
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* The AppContext is a table referenced by ThreadGroup which stores
...
...
@@ -132,10 +135,17 @@ public final class AppContext {
/* Since the contents of an AppContext are unique to each Java
* session, this class should never be serialized. */
/* The key to put()/get() the Java EventQueue into/from the AppContext.
/*
* The key to put()/get() the Java EventQueue into/from the AppContext.
*/
public
static
final
Object
EVENT_QUEUE_KEY
=
new
StringBuffer
(
"EventQueue"
);
/*
* The keys to store EventQueue push/pop lock and condition.
*/
public
final
static
Object
EVENT_QUEUE_LOCK_KEY
=
new
StringBuilder
(
"EventQueue.Lock"
);
public
final
static
Object
EVENT_QUEUE_COND_KEY
=
new
StringBuilder
(
"EventQueue.Condition"
);
/* A map of AppContexts, referenced by ThreadGroup.
*/
private
static
final
Map
<
ThreadGroup
,
AppContext
>
threadGroup2appContext
=
...
...
@@ -244,6 +254,13 @@ public final class AppContext {
return
Thread
.
currentThread
().
getContextClassLoader
();
}
});
// Initialize push/pop lock and its condition to be used by all the
// EventQueues within this AppContext
Lock
eventQueuePushPopLock
=
new
ReentrantLock
();
put
(
EVENT_QUEUE_LOCK_KEY
,
eventQueuePushPopLock
);
Condition
eventQueuePushPopCond
=
eventQueuePushPopLock
.
newCondition
();
put
(
EVENT_QUEUE_COND_KEY
,
eventQueuePushPopCond
);
}
private
static
final
ThreadLocal
<
AppContext
>
threadAppContext
=
...
...
src/share/classes/sun/awt/SunToolkit.java
浏览文件 @
a978f8f4
...
...
@@ -722,13 +722,7 @@ public abstract class SunToolkit extends Toolkit
EventQueue
eq
=
(
EventQueue
)
appContext
.
get
(
AppContext
.
EVENT_QUEUE_KEY
);
AWTAccessor
.
EventQueueAccessor
accessor
=
AWTAccessor
.
getEventQueueAccessor
();
EventQueue
next
=
accessor
.
getNextQueue
(
eq
);
while
(
next
!=
null
)
{
eq
=
next
;
next
=
accessor
.
getNextQueue
(
eq
);
}
return
(
Thread
.
currentThread
()
==
accessor
.
getDispatchThread
(
eq
));
return
accessor
.
isDispatchThreadImpl
(
eq
);
}
public
Dimension
getScreenSize
()
{
...
...
test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java
0 → 100644
浏览文件 @
a978f8f4
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 4913324
@author Oleg Sukhodolsky: area=eventqueue
@run main/timeout=30 PushPopTest
*/
import
java.awt.*
;
import
java.awt.event.*
;
import
java.util.EmptyStackException
;
import
sun.awt.SunToolkit
;
public
class
PushPopTest
{
public
static
Frame
frame
;
public
static
void
main
(
String
[]
args
)
{
frame
=
new
Frame
(
""
);
frame
.
pack
();
Runnable
dummy
=
new
Runnable
()
{
public
void
run
()
{
System
.
err
.
println
(
"Dummy is here."
);
}
};
EventQueue
seq
=
Toolkit
.
getDefaultToolkit
().
getSystemEventQueue
();
MyEventQueue1
eq1
=
new
MyEventQueue1
();
MyEventQueue2
eq2
=
new
MyEventQueue2
();
EventQueue
.
invokeLater
(
dummy
);
seq
.
push
(
eq1
);
EventQueue
.
invokeLater
(
dummy
);
eq1
.
push
(
eq2
);
EventQueue
.
invokeLater
(
dummy
);
Runnable
runnable
=
new
Runnable
()
{
public
void
run
()
{
System
.
err
.
println
(
"Dummy from SunToolkit"
);
}
};
InvocationEvent
ie
=
new
InvocationEvent
(
eq2
,
runnable
,
null
,
false
);
System
.
err
.
println
(
ie
);
SunToolkit
.
postEvent
(
SunToolkit
.
targetToAppContext
(
frame
),
ie
);
eq1
.
pop
();
frame
.
dispose
();
}
}
class
MyEventQueue1
extends
EventQueue
{
public
void
pop
()
throws
EmptyStackException
{
super
.
pop
();
}
}
class
MyEventQueue2
extends
EventQueue
{
protected
void
pop
()
throws
EmptyStackException
{
System
.
err
.
println
(
"pop2()"
);
Thread
.
dumpStack
();
try
{
EventQueue
.
invokeAndWait
(
new
Runnable
()
{
public
void
run
()
{
Runnable
runnable
=
new
Runnable
()
{
public
void
run
()
{
System
.
err
.
println
(
"Dummy from here"
);
}
};
InvocationEvent
ie
=
new
InvocationEvent
(
MyEventQueue2
.
this
,
runnable
,
null
,
false
);
SunToolkit
.
postEvent
(
SunToolkit
.
targetToAppContext
(
PushPopTest
.
frame
),
ie
);
postEvent
(
ie
);
}
});
}
catch
(
InterruptedException
ie
)
{
ie
.
printStackTrace
();
}
catch
(
java
.
lang
.
reflect
.
InvocationTargetException
ie
)
{
ie
.
printStackTrace
();
}
super
.
pop
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录