The Incrementalist

8/21/2005

Building LuaJava on Mac OS X

Filed under: — Joe @ 1:48 pm

In my previous post about coroutines, I mentioned that I’d be looking into LuaJava (a bridge between Java and the Lua language) as a way to get coroutine behavior in a Java environment. Since I had some time this afternoon, I decided to get LuaJava up and running on my PowerBook. Here are some steps that you can follow to build LuaJava on Mac OS X 10.4.2 Tiger. (I’ve also successfully tested these instructions on Mac OS X 10.3.9 Panther.)

LuaJava requires Lua 5.0, so first we need to download the Lua 5.0 source and build it:

% tar xzvf lua-5.0.tar.gz
% cd lua-5.0
% make
% sudo make install

Next, we need to build LuaJava. Download LuaJava 1.0, then extract it and switch to its directory:

% tar xzvf luajava-1.0.tar.gz
% cd luajava-1.0

Since LuaJava’s config file comes set up for Linux by default, we need to edit it to Mac OS X-friendly settings. Comment the following lines:

#JDK= $(JAVA_HOME)
#LIB_EXT= .so
#LIB_OPTION= -shared
#DLLIB= -ldl

and uncomment the corresponding ones:

JDK=/Library/Java/Home
LIB_EXT= .jnilib
LIB_OPTION= -dynamiclib -all_load

We also need to change the LIB_LUA line to read:

LIB_LUA=/usr/local/lib/liblua.a /usr/local/lib/liblualib.a

With those changes in place, we can just type

% make

and apart from a few JavaDoc warnings, everything should go smoothly. To test it, we can fire up the LuaJava Console:

% java -cp "luajava-1.0.jar" org.keplerproject.luajava.Console
API Lua Java - console mode.
> print('Hello, world!')
Hello, world!
> exit

OK, that looks good. How about the included tests?

% cd test
% ./runawttest.sh
% ./runswingtest.sh

Again, working fine. There are a couple of other Lua test files in the test directory that we can run like so:

% java -cp "../luajava-1.0.jar" -Djava.library.path=.. 
    org.keplerproject.luajava.Console testMemory.lua

(replace testMemory.lua with the name of the file you want to run)

OK, let’s try creating a program of our own. There’s a decent Hello World on the LuaJava examples page, so (after switching back to the luajava-1.0 directory), create the Hello.java and hello.lua files depicted on the examples page. You’ll need to add an import line to the top of Hello.java so that Java knows where to find all the LuaJava objects:

import org.keplerproject.luajava.*;

Once you have the files, compile the Java class:

% javac -classpath luajava-1.0.jar Hello.java

Now run it:

% java -cp luajava-1.0.jar:. Hello

If everything is working correctly, you should see:

Hello World from Lua!
Hello World from Java!

Huzzah! Now we have all the pieces we need to start embedding Lua functionality in Java code.

8/18/2005

(Lack of) Coroutines in Java

Filed under: — Joe @ 10:43 am

My current work project involves lots of small bits of code talking to each other asynchronously and requesting data from a distributed network. This means that when my code goes to retrieve a piece of data, it may be returned quickly, slowly, or not at all. Because of this uncertainty, we wouldn’t want to hold up other parts of the code while waiting for data, and so we want to put the requesting code aside and just come back to it later if and when the data arrives.

The current state of the art looks a bit like this–effectively a callback-based state machine:

Snippet establishPreference = new Snippet() {
    // called when the result of requestData is available
    public void dataReceivedCallback(Data d) {
        if (d.getValue("likes_marmalade")) {
            serveToast.requestData("marmalade");
        } else {
            serveBagel.requestData("cream cheese");
        }            
    }
}

Snippet serveToast = new Snippet() {
    public void dataReceivedCallback(Data d) {
        spreadOnToast(d.getValue("spoonful_of_substance"));                  
    }
}

Snippet serveBagel = new Snippet() {
    public void dataReceivedCallback(Data d) {
        spreadOnBagel(d.getValue("spoonful_of_substance"));
    }
}

To kick off this process, you would call:

establishPreference.requestData("Joe Hughes");

And then depending on whether I liked marmalade or not, I would eventually get served either toast with marmalade or a bagel with cream cheese.

This works fine, but you can see how it could easily get convoluted once you do any kind of serious branching or looping. For the sake of easier creation and maintenance of these things, I’d really like to be able to express these operations more like this:

Data customer = requestData("Joe Hughes");
if (customer.getValue("likes_marmalade")) {
    Data topping = requestData("marmalade");
    spreadOnToast(topping.getValue("spoonful_of_substance"));
} else {
    Data topping = requestData("cream cheese");
    spreadOnBagel(topping.getValue("spoonful_of_substance"));
}

When you put it that way, it’s much easier to see what’s going on. The problem is that in order for this to work, you have to be able to pause this block of code whenever you go off to do a requestData() call, and then restart it with result when you receive it. It turns out that what I’m describing is a somewhat obscure programming language construct called a coroutine.

Unfortunately, not many modern programming languages natively support coroutines. Python does, somewhat (through Stackless and the new Generator construct). Ruby seems to. Io and Lua do. Java, however, doesn’t.

I’ve certainly been able to use threads to make things that look like coroutines:

public abstract class PseudoCoroutine 
    implements DataListener, Runnable {

    private Data response = null;

    /**
     * This method starts a thread to run the specified task.
     *
     * @param task the PseudoCoroutine subclass to be run.
     */

    public static void doTask(PseudoCoroutine task) {
        t = new Thread(task, task.getClass().getName());
        t.start();
    }

    /**
     * This is a callback method from the DataListener interface
     * provided to the DataService to call when it has retrieved the requested data.
     *
     * @param d the data received
     */

    synchronized public void dataReceived(Data d) {
        this.response = d;
        notifyAll();
    }

    /**
     * Provides a delayed-synchronous way to perform a data request.
     * This method call will block until the response
     * is received from the server. 
     *
     * @param dataID the ID of the data to be requested.
     * @return A Data object corresponding to the requested dataID.
     * @throws InterruptedException
     */

    protected Data requestData(String dataID) throws InterruptedException {
        // second parameter is used to pass this.dataReceived() as a callback
        DataService.getInstance().requestData(dataID, this);

        synchronized (this) {
            while (this.response == null) {
                wait();
            }
        }

        return this.response;
    }

    // to make this a Runnable that can be passed to a thread
    public void run() {
        taskBody();
    }

    /**
     * This is where the PseudoCoroutine subclass should perform its task.
     */

    public abstract void taskBody();
}

This class lets me just use the code I had written above:

private class ServeBreakfastBread extends PseudoCoroutine {
    private String customerID;

    public ServeBreakfastBread(String customerID) {
        this.customerID = customerID;
    }

    public void taskBody() {
        Data customer = requestData(customerID);
        if (customer.getValue("likes_marmalade")) {
            Data topping = requestData("marmalade");
            spreadOnToast(topping.getValue("spoonful_of_substance"));
        } else {
            Data topping = requestData("cream cheese");
            spreadOnBagel(topping.getValue("spoonful_of_substance"));
        }
    }    
}

...

PseudoCoroutine.doTask(new ServeBreakfastBread("Joe Hughes"));

This works fine, except that each of these things now requires an OS thread, with their attendant limitations (good luck getting more than a few thousand on a desktop VM). I’d also like to have the ability for several of these coroutines to be able to operate on common state information without lots of synchronization hassle, which I can’t do if each coroutine lives in its own thread.

So, where to now? Maybe I can embed another language interpreter within my Java system and express the coroutines in that. Unfortunately, Jython doesn’t support Generators yet. I’ll have to look into LuaJava and JRuby to see if they have anything to offer.

12/28/2004

Starting a system drag on a mouseExited event

Filed under: — Joe @ 8:41 pm

Exit Drag

Swing’s drag-and-drop implementation is pretty straightforward for the common cases—if you’re working with standard components, you might not have to do any work at all to get basic drag-and-drop support. However, once you get to the point of wanting to do interesting nonstandard things, it’s easy to get tangled up in the web of interrelated UI classes, many of which can’t just be constructed.

Case in point: in certain parts of my application, I’d like item dragging to be rendered by my component up until the point at which the cursor crosses the component’s boundary. It’s simple to start a system drag when at the point at which the user clicks the cursor on an item—but I want the system drag to start only when the component gets a mouseExited() during an in-component drag. After a bit of experimentation, I found that I could accomplish this using a custom, somewhat corrupt DragGestureRecognizer (application-specific code indicated by $dollar signs$):

private class ExitDragGestureRecognizer 
    extends DragGestureRecognizer {
    public ExitDragGestureRecognizer(Component comp) {
        super(DragSource.getDefaultDragSource(), comp);
    }

    public synchronized int getSourceActions() {
        return DnDConstants.ACTION_COPY_OR_MOVE;
    }

    protected void registerListeners() {}

    protected void unregisterListeners() {}

    public void setEvent(InputEvent e) {
        resetRecognizer();
        appendEvent(e);
    }
}

private ExitDragGestureRecognizer dgr = 
    new ExitDragGestureRecognizer($myPanel$);

Then, in the component’s attached MouseListener, the following code transfers from a local to a system drag when the cursor hits the component boundary:

public void mouseExited(MouseEvent e) {
    if ($inLocalDrag()$) {
        Transferable trans = $getDragTransferable()$;
        DragSource source = DragSource.getDefaultDragSource();
        DragGestureEvent event = 
            new DragGestureEvent(dgr, DnDConstants.ACTION_COPY,
            $localDragStartPoint$, Collections.singletonList(e))
        dgr.setEvent(e);
        source.startDrag(event, DragSource.DefaultCopyDrop, 
            trans, null);

        $endLocalDrag()$;
    }
}

In my testing, this seemed to work under J2SE 1.4+ on Windows XP and Mac OS X 10.3.7. It’s really not all that difficult, but the only way I was able to figure it out was just by guessing at calls and seeing where they failed. If anyone knows of a good in-depth Swing reference that talks addresses this sort of thing, please let me know.

12/24/2004

Mac OS X Graphic Performance Tidbits

Filed under: — Joe @ 9:46 am

Quartz Debug

Lately I’ve been digging into the details of the Mac OS X graphics subsystem, both because a lot of my (Java) code exercises it, and partly because I might be building something similar at some point.

OS X owes its renowned visual stability to the fact that every single window is buffered; to be exact, drawing commands from programs are executed into offscreen buffers, which are flushed to the screen (with an eye to where the CRT beam is!) when WaitNextEvent or QDFlushPortBuffer are called. Keeping a bitmap for each window is what allows OS X to sling windows around without visual glitching, even when applications are frozen up compeletely. It is, of course, a very expensive proposition in terms of the system RAM that it consumes. It hadn’t sunk in for me before that every single open window, visible or not, eats up significant RAM—maybe that’ll convince me to close old windows a little more often, especially on my poor 640MB iBook.

The other thing that I had heard about before but hadn’t tried before is the Quartz Debug utility, which you’ll find in /Developer/Applications/Performance Tools/Quartz Debug if you have the Developer Tools installed on your machine. If you run that and check off Flash screen updates (yellow) and No delay after flash, you’ll get a nice view into the workings of the graphics system, because any area of the screen buffer that changes will flash yellow. One interesting thing that this makes apparent is an advantage that Safari has over Firefox: when scrolling, Safari updates only the newly-exposed area of the window, making for smoother scrolling than Firefox, which always redraws the whole content pane. Another thing that it made obvious to me is how horribly inefficient some parts of the Geobrowser are in terms of redrawing things which haven’t changed visually—I need to be more conscientious about calling repaint() with an affected area and minding the clip rectangle in paintComponent(). (It actually makes me happy to discover clear-cut avenues for optimization like that.)

I’m still looking for real nuts-and-bolts details on what happens during screen updates. Here’s the mental model that I’ve pieced together so far:

  1. An application performs some drawing operations, which modify an offscreen window buffer #1
  2. The application calls QDFlushPortBuffer with an affected region rectangle, which blocks while…
  3. The affected region of the application window is blitted from buffer #1 to buffer #2 (the Window Server’s buffer for that window)
  4. The affected region of the screen is re-composited by Quartz Compositor (Extreme or otherwise) and blitted to the frame buffer when the CRT beam or LCD refresh point is elsewhere

If you know better and I’m getting some details wrong, don’t hesitate to comment.

12/19/2004

Animated Transitions in Java

Filed under: — Joe @ 8:57 pm

An inspired bit of hackery by Dmitry Markman led to a flurry of collaborative development on Apple’s java-dev mailing list, and the result is a handy AnimatingCardLayout class that provides a variety of animated transitions between two Swing panels. It’s not nearly as smooth as the OS X effects that inspired it, but it may be as good as it gets without more direct access to graphics hardware from Java. Visit Dmitry’s site to see demo applets and get the source.

[Update] The project now has a permanent home at java.net.