Saturday, 21 April 2012
Some (routine) "tricky corners" in Java
When Sam and I were trying to develop analogies between jazz improvisation and live coding, Nick Cook told us that preparation for performance might involve rehearsing "tricky corners" that can arise in a particular improvisation genre. Although I'm not coding anything live, there are some kinds of software development task that always leave me feeling a little nervous, no matter what language I'm working in. One of these is management of realtime threads. Another is interacting with a new file system for the first time.
So in the past week, I've taken some deep breaths, and plunged into both of these. Both are routine enough, and every Java programmer (or teacher of Java programming) knows what to do - but as always, newcomers have to learn it themselves.
I'd already created a number of Java animation threads during the project, and had got accustomed to the use of SwingWorkers and timers to ensure that the system still responds to user interaction while doing memory-intensive image shuffling. I'd speeded up some of these animations with better double-buffering of the layer rendering, separating fast animated components from relatively static elements that can be updated less often,
But lately there have been too many animations all running concurrently, now that some state variables are animated (the rate and event value types), and these control other animated layers (paths) that themselves interact with or control other layers. After some encouragement from James Noble (still visiting), I therefore aggregated all the animated updates into an update task list that is reviewed and updated in a single animation thread - James tells me this is how Smalltalk does it, and that's good enough for me! However, several days of thread debugging ensued. James was off at a recording session, and it turns out could have told me immediately what my problem was - but what I thought was a subtle deadlock problem turned out to be the simple fact that exceptions in background Java threads die silently if the thread invocation wasn't made within a try-catch block. So my problem was simply an invisible null pointer exception. Once I'd learned to catch this and dump a stack trace, it became relatively easy to debug the threaded animation.
The second plunge was into Java persistence, which I've never had any reason to use before. It seems about time that my "programs" (quote marks necessary until I persuade James that this really is a programming language) can be saved by the user - at least, it is now possible to create things sufficiently complex that I might want to recover them in future. The illustration on todays post is a "Mr Watson, come here" - the first layer successfully saved and dragged back into a new Palimpsest session. As with my complex animation thread, there had been good reason for nerves - the order in which persistent objects are written to a stream is not that easy to anticipate, meaning that getting a complex class hierarchy persisted involves several hours of trial and error, with many exceptions along the way.