RR

Flyers 2000-2004

December 26, 2005

whiteout may 4 vs leukemia Posted a bunch of old party flyers I designed 2000-2004. Some were for club nights at places that no longer exist: Townsend/King Street Garage (torn down in 2004 and now a loft building) and Sno-Drift (shuttered earlier this year). Some were for house parties.

Need to have a party in the new house at some point...

Caution PCBs

December 26, 2005

caution pcbsFrom a set of photos taken of the ruined munitions plant in Hunter's Point.

Canvas Implementations

December 26, 2005

Both Mozilla and the Webkit folks fixed the bugs I noticed with their <canvas> implementations. It was pretty nice to see someone make a Doom-style renderer using the same method I had been attempting at the time.

About This Design

December 26, 2005

The design of this blog started out as a generic two-column-right template, modified using Custom CSS. I wanted to have a fluid design without fluid column widths. What I did was fix the primary content column (alpha) to a specific width, and then canned the secondary column as a hard & fast container.

The content modules in the right side are fixed width and float left. They are sized such that 3 of them across is equal to the alpha column. On short pages like the Archives page, the sidebar modules wrap nicely around the main content area.

It will probably take some tweaking over the next few weeks until everything is hammered down.

Update 1: Shaved 5-10px off the column widths so that 2 columns fits on an 800x600 screen, 1 column on 640x480, and 3 columns at 1024 pixels wide.

Update 2: Converted the design to Advanced Templates because of a bug in IE6, where the containing div around a set of floats, even position: static and float: none would still wrap the floated elements.

Continuations in JavaScript

December 25, 2005

...or why they can't work the way I want them to.

I was reading Simon Tatham's brilliant essay on Coroutines in C the other day after hunting around to see if anyone had implemented continuations in JavaScript. This is a jumbled account of how I came to want and fail to make them work (yet).

JavaScript is a wonderful language, it has the expressiveness of Perl with the syntactic clarity of Java. As much as I love Perl, sigils have always bugged me a little and I really really like writing single-line blocks without braces or inverting the order as Perl requires.

A lot of the stuff I've been writing lately fits a basic pattern: object A calls a method on object B and supplies a callback so that when the operation is completed, object B can supply object A with the result. Generally the sort of thing that object B does involves making a request to the server or querying the user for some information.

An example of this would be a modified window.confirm() method. Assume your favorite browser overloads the function with an additional argument: window.confirm( message, callback ) The function would return immediately, returning control to the calling function and after the user clicks OK or Cancel, the callback function is called with a single value of true or false.

function step() {
    var message = "Your mouse position has changed. "+
        "Click OK to confirm the change or " +
        "Cancel to return to the original position.";
    window.confirm( message, correct );
}

function correct( result ) {
    if( result )
        revertMouse();
}

Callbacks work pretty well. Since JavaScript supports lexical closures, it's trivial to create a closure that simply wraps the this object and a particular method. Our core.js has two factory methods for doing just that: bind() and bindEventListener(). Our example rewritten as a class:

Annoy = new Class( Object, {
    step: function() {
        var message = "Your mouse position has changed. "+
            "Click OK to confirm the change or " +
            "Cancel to return to the original position.";
        window.confirm( message, this.correct.bind( this ) );
    },
    

    correct: function( result ) {
        if( result )
            revertMouse();
    }
} );

This works pretty well, to a point. If you need to set up multiple levels of asynchronous calls, the code degenerates pretty quickly. Callbacks calling other callbacks, creating closures around other closures, generally doing a good job of concealing or at least confusing the actual flow of the program.

This is especially obvious with AJAX. Ideally you don't want to use a blocking request, tying up the UI in JavaScript, holding the browser hostage. Making asychronous requests to the server end up looking a lot like the above example:

ServerList = new Class( Object, {
    init: function( id ) {
        this.id = id;
        this.length = 0;
    },
    
    
    getItems: function( index, length, callback ) {
        var _this = this;
        AJAX.call( "getItems", [ this.id, index, length ],
            function( response ) {
                _this.handleResult( response.result, callback );
            } );
    },
    

    handleResult: function( result, callback ) {
        this.length = result.length;
        callback( result.items );
    }
} );

The ServerList class is a model, and there's another class that acts as the view. It handles rendering the list, handling user events, etc. There's a producer-consumer relationship between the model and view classes, and a p-c relationship between the model and the server. Since requesting items from the server is an asynchronous operation, the view class must have a callback (and therefore another closure) to accept the results from a call to the getItems() method. Just one level deeper, and the ratio of algorithm complexity to code complexity has noticably worsened. The logical flow of the program is obscured in a pair of callbacks and closures in two classes.

The view class is completely dependent on the model class to supply it with information. The callback supplied on every request could be replaced with a single call to instantiate the relationship between the two objects:

ServerList = new Class( Object, {
    init: function( id ) {
        this.id = id;
        this.length = 0;
        this.observers = [];
    },
    
    
    observe: function( observer ) {
        this.observers.add( observer );
    },
    
    
    unobserve: function( observer ) {
        this.observers.remove( observer );
    },
    
    
    getItems: function( index, length ) {
        var _this = this;
        AJAX.call( "getItems", [ this.id, index, length ],
            this.handleResponse.bind( this ) );
    },
    

    handleResponse: function( response ) {
        var result = response.result;
        this.length = result.length;
        this.observers.forEach( function( observer ) {
                if( observer.itemsLoaded )
                    observer.itemsLoaded( result.items );
            } );
    }
} );

All an observing object needs to have is a specified method that the producer recognizes for passing items. In this case it's itemsLoaded(). The ServerList class could have multiple observers who can all be notified when new items are loaded. They can determine if and what to do with that data. A hypothetical view class:

ServerView = new Class( Object, {
    init: function( list ) {
        this.list = list;
        this.list.observe( this );
        
        this.offset = 0;
        this.length = 10;
        this.items = [];
        this.loaded = false;
    },
    
    
    setOffset: function( offset ) {
        this.offset = offset;
        this.loaded = false;
        this.draw();
    },
    
    
    draw: function() {
        if( !this.loaded ) {
            this.list.getItems( this.offset, this.length );
            return;
        }
        
        var html = "";
        this.items.forEach( function( item ) {
                html += "

" + item.index + ": " + item.name + "

"; } ); document.body.innerHTML = html; }, itemsLoaded: function( items ) { items.forEach( function( item ) { var index = item.index - this.offset; if( item.index < 0 || item.index >= this.length ) continue; this.items[ index ] = item; } ); this.loaded = true; this.draw(); } } );

Now the complexity has been mostly moved to the view class. Whether the result is preferable to using callbacks is debatable. An object with a lot of observers could result in a lot of noisy traffic, calling methods on observers when they don't care about the result.

After mucking through the first two options, I realized what I really wanted was continuations. I want to be able to call a JavaScript function that will return after some amount of time with a response, returning control back to my function. I wanted to turn the draw() function into something resembling this:

    draw: function() {
        var items = this.list.getItems.yield( this.offset, this.length );
        ...
    }

The idea being that the state of draw() would be saved while getItems() went on its merry way to get the data. The draw() method would return immediately at the getItems.yield() call and only when that completed would the remainder of the function be called.

So I started hacking on it a bit after reading Simon's article on continuations in C. I figured the same thing could be hacked using closures and goto. All I would need to do is have a function recompiler that modified a method or function, wrapping the contents in a closure and declaring all lexicals outside the closure. Essentially a continuation factory. So my first stab at what a generated function would look like was this:

Before:

function test() {
    var count; // predeclaring all lexicals to simplify function recompiler
    
    count = 0;
    while( 1 ) {
        sleep( 500 );
        document.body.appendChild(
            document.createTextNode( count + " " ) );
        count++;
    }
}

After:

function test() {
    var count;
    var continuation = function( rval ) {
        if( !continuation.label ) {
            count = 0;
            while( 1 ) {
                window.setTimeout( continuation, 500 );
                continuation.label = 1;
                return;
            __1:
                document.body.appendChild(
                    document.createTextNode( count + " " ) );
                count++;
            }
            __1: ;
        } else {
            while( 1 ) {
                if( continuation.label == 1 )
                    break __1;
                return;
            }
           
        }
    }
   
    return continuation();
}

I had been hoping to use either break or continue as a substitute for goto. Alas, when compiled Firefox complains that label __1 is missing. So I'm at a stopping point. There doesn't seem to be a way (in normal JavaScript anyway) to jump into a loop or other lexical block.

Anyone have any ideas?

The Wheel

February 28, 2005

Got the wheel from Gravy today. It weighs 6.25 pounds (2.8 kg). (!)

Frame Progress

February 6, 2005

Frankenbike_0000

Went to see Bernie today, and the frame looks good. The lugs are nice and pointed, the brazing is clean, the frame is straight and the couplers are in. The matching fork with its single lugged crown and double eyelets is a piece of work. As soon as Bernie gets the Rohloff hub, he can position the disc brake mount and torque braze-ons.

Lugged steel is a thing of beauty. Bernie added an inch or so of extension brazed onto the top of the headtube lug to raise the handlebars a bit without having to resort to too many spacers (not that that scares him, anyway...some of his bikes have steerer tubes half again as long as the fork blades). Soon all the parts will come together (frame, racks, hubs, brakes, cables) and the puzzle of fitting it all together.

The Frankenbike

January 30, 2005

bizdeviant: what is the current iteration of franken rig?

For a long time I've wanted a touring bike. Not just any touring bike, but something interesting. It had to be bomb-proof, but at the same time worthy of a conversation or two, i.e. containing some bull-headed unique little feature that makes it different from every other bike out there. Just to be difficult.

I decided a while ago that my perfect touring bicycle would use a Rohloff internal gear hub. It has 14 linearly-spaced speeds, works with a QR, and can be hit with a nuclear missle etc. and still function. It weighs a ton, costs more than the components it replaces, and most importantly lets me ride with a single chainring, one cog, and no derailleurs. Despite the plethora of cables, the bicycle will at least have the same clean appearance as a single-speed.

AIDS LifeCycle 3

December 12, 2003

Originally posted to shaderlab.com on December 11, 2003.

SF2LA

SFAF On June 6-12 2004 I’m riding in the AIDS LifeCycle ride from SF to LA for the San Francisco AIDS Foundation. 7 days, 585 miles on a bicycle.

The SFAF is a nonprofit organization that provides treatment and other services to men and women infected with HIV/AIDS, both locally in San Francisco and globally via Pangea Global AIDS Foundation. My goal is to raise at least $5000 for the SFAF by June. If you’d like to be a sponsor, click here to donate. No contribution is too small.

Anyway, if you’ve ever used my textures or Q3Map2 (or whatever) and wanted to give something back (or just buy me a pint), donate here.

Happy Birthday Q3Map2

December 3, 2003

Originally posted to shaderlab.com on December 3, 2003.

Q3Map2 2 YearsTwo years ago today, I released the first version of what eventually became Q3Map2. It’s been a long, fun trip. Thanks to everyone who used it, contributed to it, debugged and beta tested it, complained about it, and made working on it worthwhile.

Here’s to another 2 years, uh, doing...something.