6784816: Remove AWT tree lock from Container methods: getComponent, getComponents, getComponentCount

Reviewed-by: anthony, dav
This commit is contained in:
Artem Ananiev 2009-03-04 18:10:48 +03:00
parent 8a7cd86a28
commit e63a1bf460

View File

@ -270,9 +270,13 @@ public class Container extends Component {
/** /**
* Gets the number of components in this panel. * Gets the number of components in this panel.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @return the number of components in this panel. * @return the number of components in this panel.
* @see #getComponent * @see #getComponent
* @since JDK1.1 * @since JDK1.1
* @see Component#getTreeLock()
*/ */
public int getComponentCount() { public int getComponentCount() {
return countComponents(); return countComponents();
@ -284,43 +288,65 @@ public class Container extends Component {
*/ */
@Deprecated @Deprecated
public int countComponents() { public int countComponents() {
synchronized (getTreeLock()) { // This method is not synchronized under AWT tree lock.
return component.size(); // Instead, the calling code is responsible for the
} // synchronization. See 6784816 for details.
return component.size();
} }
/** /**
* Gets the nth component in this container. * Gets the nth component in this container.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @param n the index of the component to get. * @param n the index of the component to get.
* @return the n<sup>th</sup> component in this container. * @return the n<sup>th</sup> component in this container.
* @exception ArrayIndexOutOfBoundsException * @exception ArrayIndexOutOfBoundsException
* if the n<sup>th</sup> value does not exist. * if the n<sup>th</sup> value does not exist.
* @see Component#getTreeLock()
*/ */
public Component getComponent(int n) { public Component getComponent(int n) {
synchronized (getTreeLock()) { // This method is not synchronized under AWT tree lock.
if ((n < 0) || (n >= component.size())) { // Instead, the calling code is responsible for the
throw new ArrayIndexOutOfBoundsException("No such child: " + n); // synchronization. See 6784816 for details.
} try {
return component.get(n); return component.get(n);
} catch (IndexOutOfBoundsException z) {
throw new ArrayIndexOutOfBoundsException("No such child: " + n);
} }
} }
/** /**
* Gets all the components in this container. * Gets all the components in this container.
* <p>
* Note: This method should be called under AWT tree lock.
*
* @return an array of all the components in this container. * @return an array of all the components in this container.
* @see Component#getTreeLock()
*/ */
public Component[] getComponents() { public Component[] getComponents() {
// This method is not synchronized under AWT tree lock.
// Instead, the calling code is responsible for the
// synchronization. See 6784816 for details.
return getComponents_NoClientCode(); return getComponents_NoClientCode();
} }
// NOTE: This method may be called by privileged threads. // NOTE: This method may be called by privileged threads.
// This functionality is implemented in a package-private method // This functionality is implemented in a package-private method
// to insure that it cannot be overridden by client subclasses. // to insure that it cannot be overridden by client subclasses.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD! // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
final Component[] getComponents_NoClientCode() { final Component[] getComponents_NoClientCode() {
return component.toArray(EMPTY_ARRAY);
}
/*
* Wrapper for getComponents() method with a proper synchronization.
*/
Component[] getComponentsSync() {
synchronized (getTreeLock()) { synchronized (getTreeLock()) {
return component.toArray(EMPTY_ARRAY); return getComponents();
} }
} // getComponents_NoClientCode() }
/** /**
* Determines the insets of this container, which indicate the size * Determines the insets of this container, which indicate the size
@ -1028,9 +1054,9 @@ public class Container extends Component {
} }
checkAddToSelf(comp); checkAddToSelf(comp);
checkNotAWindow(comp); checkNotAWindow(comp);
if (thisGC != null) { if (thisGC != null) {
comp.checkGD(thisGC.getDevice().getIDstring()); comp.checkGD(thisGC.getDevice().getIDstring());
} }
/* Reparent the component and tidy up the tree's state. */ /* Reparent the component and tidy up the tree's state. */
if (comp.parent != null) { if (comp.parent != null) {
@ -1349,7 +1375,7 @@ public class Container extends Component {
} }
private int getListenersCount(int id, boolean enabledOnToolkit) { private int getListenersCount(int id, boolean enabledOnToolkit) {
assert Thread.holdsLock(getTreeLock()); checkTreeLock();
if (enabledOnToolkit) { if (enabledOnToolkit) {
return descendantsCount; return descendantsCount;
} }
@ -1367,7 +1393,7 @@ public class Container extends Component {
final int createHierarchyEvents(int id, Component changed, final int createHierarchyEvents(int id, Component changed,
Container changedParent, long changeFlags, boolean enabledOnToolkit) Container changedParent, long changeFlags, boolean enabledOnToolkit)
{ {
assert Thread.holdsLock(getTreeLock()); checkTreeLock();
int listeners = getListenersCount(id, enabledOnToolkit); int listeners = getListenersCount(id, enabledOnToolkit);
for (int count = listeners, i = 0; count > 0; i++) { for (int count = listeners, i = 0; count > 0; i++) {
@ -1382,7 +1408,7 @@ public class Container extends Component {
final void createChildHierarchyEvents(int id, long changeFlags, final void createChildHierarchyEvents(int id, long changeFlags,
boolean enabledOnToolkit) boolean enabledOnToolkit)
{ {
assert Thread.holdsLock(getTreeLock()); checkTreeLock();
if (component.isEmpty()) { if (component.isEmpty()) {
return; return;
} }
@ -1517,6 +1543,7 @@ public class Container extends Component {
* @see #validate * @see #validate
*/ */
protected void validateTree() { protected void validateTree() {
checkTreeLock();
if (!isValid()) { if (!isValid()) {
if (peer instanceof ContainerPeer) { if (peer instanceof ContainerPeer) {
((ContainerPeer)peer).beginLayout(); ((ContainerPeer)peer).beginLayout();
@ -1793,7 +1820,7 @@ public class Container extends Component {
// super.paint(); -- Don't bother, since it's a NOP. // super.paint(); -- Don't bother, since it's a NOP.
GraphicsCallback.PaintCallback.getInstance(). GraphicsCallback.PaintCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.LIGHTWEIGHTS); runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
} }
} }
@ -1848,7 +1875,7 @@ public class Container extends Component {
} }
GraphicsCallback.PrintCallback.getInstance(). GraphicsCallback.PrintCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.LIGHTWEIGHTS); runComponents(getComponentsSync(), g, GraphicsCallback.LIGHTWEIGHTS);
} }
} }
@ -1861,7 +1888,7 @@ public class Container extends Component {
public void paintComponents(Graphics g) { public void paintComponents(Graphics g) {
if (isShowing()) { if (isShowing()) {
GraphicsCallback.PaintAllCallback.getInstance(). GraphicsCallback.PaintAllCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.TWO_PASSES); runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
} }
} }
@ -1883,8 +1910,8 @@ public class Container extends Component {
void paintHeavyweightComponents(Graphics g) { void paintHeavyweightComponents(Graphics g) {
if (isShowing()) { if (isShowing()) {
GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance(). GraphicsCallback.PaintHeavyweightComponentsCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.LIGHTWEIGHTS | runComponents(getComponentsSync(), g,
GraphicsCallback.HEAVYWEIGHTS); GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
} }
} }
@ -1897,7 +1924,7 @@ public class Container extends Component {
public void printComponents(Graphics g) { public void printComponents(Graphics g) {
if (isShowing()) { if (isShowing()) {
GraphicsCallback.PrintAllCallback.getInstance(). GraphicsCallback.PrintAllCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.TWO_PASSES); runComponents(getComponentsSync(), g, GraphicsCallback.TWO_PASSES);
} }
} }
@ -1919,8 +1946,8 @@ public class Container extends Component {
void printHeavyweightComponents(Graphics g) { void printHeavyweightComponents(Graphics g) {
if (isShowing()) { if (isShowing()) {
GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance(). GraphicsCallback.PrintHeavyweightComponentsCallback.getInstance().
runComponents(component.toArray(EMPTY_ARRAY), g, GraphicsCallback.LIGHTWEIGHTS | runComponents(getComponentsSync(), g,
GraphicsCallback.HEAVYWEIGHTS); GraphicsCallback.LIGHTWEIGHTS | GraphicsCallback.HEAVYWEIGHTS);
} }
} }
@ -2470,9 +2497,7 @@ public class Container extends Component {
* @since 1.2 * @since 1.2
*/ */
public Component findComponentAt(int x, int y) { public Component findComponentAt(int x, int y) {
synchronized (getTreeLock()) { return findComponentAt(x, y, true);
return findComponentAt(x, y, true);
}
} }
/** /**
@ -2485,58 +2510,60 @@ public class Container extends Component {
* The addition of this feature is temporary, pending the * The addition of this feature is temporary, pending the
* adoption of new, public API which exports this feature. * adoption of new, public API which exports this feature.
*/ */
final Component findComponentAt(int x, int y, boolean ignoreEnabled) final Component findComponentAt(int x, int y, boolean ignoreEnabled) {
{ synchronized (getTreeLock()) {
if (isRecursivelyVisible()){ if (isRecursivelyVisible()){
return findComponentAtImpl(x, y, ignoreEnabled); return findComponentAtImpl(x, y, ignoreEnabled);
}
} }
return null; return null;
} }
final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){ final Component findComponentAtImpl(int x, int y, boolean ignoreEnabled){
checkTreeLock();
if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) { if (!(contains(x, y) && visible && (ignoreEnabled || enabled))) {
return null; return null;
} }
// Two passes: see comment in sun.awt.SunGraphicsCallback // Two passes: see comment in sun.awt.SunGraphicsCallback
synchronized (getTreeLock()) { for (int i = 0; i < component.size(); i++) {
for (int i = 0; i < component.size(); i++) { Component comp = component.get(i);
Component comp = component.get(i); if (comp != null &&
if (comp != null && !(comp.peer instanceof LightweightPeer)) {
!(comp.peer instanceof LightweightPeer)) { if (comp instanceof Container) {
if (comp instanceof Container) { comp = ((Container)comp).findComponentAtImpl(x - comp.x,
comp = ((Container)comp).findComponentAtImpl(x - comp.x, y - comp.y,
y - comp.y, ignoreEnabled);
ignoreEnabled); } else {
} else { comp = comp.locate(x - comp.x, y - comp.y);
comp = comp.locate(x - comp.x, y - comp.y);
}
if (comp != null && comp.visible &&
(ignoreEnabled || comp.enabled))
{
return comp;
}
} }
} if (comp != null && comp.visible &&
for (int i = 0; i < component.size(); i++) { (ignoreEnabled || comp.enabled))
Component comp = component.get(i); {
if (comp != null && return comp;
comp.peer instanceof LightweightPeer) {
if (comp instanceof Container) {
comp = ((Container)comp).findComponentAtImpl(x - comp.x,
y - comp.y,
ignoreEnabled);
} else {
comp = comp.locate(x - comp.x, y - comp.y);
}
if (comp != null && comp.visible &&
(ignoreEnabled || comp.enabled))
{
return comp;
}
} }
} }
} }
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if (comp != null &&
comp.peer instanceof LightweightPeer) {
if (comp instanceof Container) {
comp = ((Container)comp).findComponentAtImpl(x - comp.x,
y - comp.y,
ignoreEnabled);
} else {
comp = comp.locate(x - comp.x, y - comp.y);
}
if (comp != null && comp.visible &&
(ignoreEnabled || comp.enabled))
{
return comp;
}
}
}
return this; return this;
} }
@ -3491,7 +3518,7 @@ public class Container extends Component {
private void writeObject(ObjectOutputStream s) throws IOException { private void writeObject(ObjectOutputStream s) throws IOException {
ObjectOutputStream.PutField f = s.putFields(); ObjectOutputStream.PutField f = s.putFields();
f.put("ncomponents", component.size()); f.put("ncomponents", component.size());
f.put("component", component.toArray(EMPTY_ARRAY)); f.put("component", getComponentsSync());
f.put("layoutMgr", layoutMgr); f.put("layoutMgr", layoutMgr);
f.put("dispatcher", dispatcher); f.put("dispatcher", dispatcher);
f.put("maxSize", maxSize); f.put("maxSize", maxSize);