NOTICE: This version of the NSF Unidata web site (archive.unidata.ucar.edu) is no longer being updated.
Current content can be found at unidata.ucar.edu.
To learn about what's going on, see About the Archive Site.
Hi Stuart, Thanks for pointing this out. I'll take a look at it in more detail later this week, but initially I do have one comment. Rather than using interrupts, a slightly cleaner way would be to use monitors with wait and notifyAll, like the code is already doing. It might take slightly longer than interrupt in certain cases (I'm not sure), but it gives you more control over the flow of the code. For example, the graphics context will always get properly disposed. -Curtis On 10/26/07, stuart@xxxxxxxxxxxxxxxxxx <stuart@xxxxxxxxxxxxxxxxxx> wrote: > I have mostly tried to use visad for offscreen rendering, from servlets in > web apps. The intention was > > DisplayImpl di = new DisplayImplJ2D( "", w, h ); > BufferedImage bi = di.getImage(true); > di.destroy(); > > As you would expect, we want the net memory footprint of the above > sequence to be just the BufferedImage, which we can save to disk or use a > servlet to serialize to some web client. Thus the net footprint is then > zero. This is vital in a long lived app like a web site. > > I have always had problems, frequently exhausting memory. I should point > out that I am trying to render some large images, on the order of 6000 x > 6000, but really that is beside the point, it just makes the outofmemory > occur earlier. > > Finally, after about 3 years of looking at this, I think have a solution. > It now seems obvious why it was failing at all. > > In VisADCanvasJ2D, we have > > stop() { > renderThread =null; > } > > and > > run() { > while ( renderThread != null ) { > do some work; > wait for more work; > } > > The problem is that the stop code is not powerful enough to halt the run > code. At any given point in time, the run code (the renderThread) can be > anywhere in its loop. If it is in wait, it will stay there forever. The > thread is live, thus the canvas it references (the Runnable) is also, and > so are any BufferedImages we have built. we cannot GC any of it. > > > We need to raise an interrupt in this thread. This will get us out of a > wait call, if the interrupt is posted either before or during the wait. I > think the soln is this > > volatile boolean done = false; > > stop () { > done = true; > renderThread.interrupt(); > renderThread.join(); > } > > run() { > while( !done ) { > try { > do some work; > wait; > } catch( InterruptedException ie ) { > } > } > } > > This makes the calling program , which calls stop via the > DisplayImpl.destroy(), wait for the renderThread to finish. We need the > boolean done, we cannot do this from stop: > > renderThread.interrupt(); > renderThread = null; > > since the run could get the interrupt, test the renderThread for non null > and do another wait, all before the stop can set the renderThread to null > ( i have tested this and seen it occur). > > Initially i coded the joining of the calling (application) thread and > renderThread using a CountdownLatch set to 1, from java.util.concurrent, > with stop doing a latch.await() and run doing a latch.countDown() as its > final action, but the thread join seems equivalent to that (anyone??). > > One caveat of raising the interrupt on the renderThread is that somewhere > in the 'do some work' the newly raised interrupt can lead to an abort of > the work. But we dont really care, since we have got our image via > getImage and then called destroy in that order. > > I hope this helps anyone trying to use Visad in offscreen mode, > particularly in webapps. > > Comments welcomed. > > Stuart > > > _______________________________________________ > visad mailing list > visad@xxxxxxxxxxxxxxxx > For list information, to unsubscribe, visit: > http://www.unidata.ucar.edu/mailing_lists/ >
visad
archives: