Preparing for the 0.2 draft
Peter Levart
peter.levart at marand.si
Wed Feb 3 23:54:35 PST 2010
On Thursday 04 February 2010 06:56:35 Joshua Bloch wrote:
> (22) src/share/classes/javax/swing/BufferStrategyPaintManager.java:213
>
> OH MY GOD! This code has four uses of this. Three are silly (necessitated
> by the fact that the the run method has a local variable with the same name
> as a field in the enclosing class, as in (4) above). One is horribly
> broken:
>
> SwingUtilities.invokeLater(new Runnable() {
> public void run() {
> java.util.List<BufferInfo> bufferInfos;
> synchronized(BufferStrategyPaintManager.this) {
> while (showing) {
> try {
> wait();
> } catch (InterruptedException ie) {
> }
> }
> bufferInfos =
> BufferStrategyPaintManager.this.bufferInfos;
> BufferStrategyPaintManager.this.bufferInfos = null;
> }
> dispose(bufferInfos);
> }
> });
>
> Note that the code is waiting on the anonymous instance, but synchronizing
> on the containing BufferStrategyPaintManager instance. This will throw an
> IllegalMonitorStateException as soon as it waits! This is definitely a bug.
> I wonder why it hasn't been reported.
>
> So what's the right solution? You could fix this by using
> BufferStrategyPaintManager.this twice, but this is ugly and error prone.
> Better would be to uses something higher-level than wait/notify. If you did
> that, you wouldn't need to access BufferStrategyPaintManager.this at all.
>
Was this code written before the JDK 5 days maybe? I think that what is interesting is that it shows an example where the block of code, posing as Runnable, has no identity of it's own - it goes to great lengths in an attempt to be executed in the surrounding context, not succeeding entirely as a call to wait() escaped the programmer's eye. This is the class of examples that would benefit from entirely transparent lambdas. Lambdas where even unqualified "equals(), hashCode(), wait(), notify(), getClass()" were executed in the surrounding context. Let's see how such lambdas would affect the rewrite of this example:
/**
* Cleans up any created BufferStrategies.
*/
protected void dispose() {
// dipose can be invoked at any random time. To avoid
// threading dependancies we do the actual diposing via an
// invokeLater.
SwingUtilities.invokeLater(#() {
java.util.List<BufferInfo> bufferInfos;
synchronized(this) {
while (showing) {
try {
wait();
} catch (InterruptedException ie) {
}
}
bufferInfos = this.bufferInfos;
this.bufferInfos = null;
}
dispose(bufferInfos);
});
}
I don't know, but am I the only one that notices the beauty and simplicity of such solution?
Regards, Peter
More information about the lambda-dev
mailing list