Adventures in Squeak

This weekend I spent a bit of time playing with Squeak (as my non-commercial Gemstone/S was missing a valid license key, so the plan to play with that went out the window).

Starting simply, I tried the following, based on some example code:

HTTPSocket httpShowPage: ''

Sure enough, up popped a window with the raw html of my homepage.

Wanting to try out multiple requests, I modified the code to this:

10 timesRepeat:[HTTPSocket httpShowPage: ''].

After a significant pause, 10 windows appeared one after the other. This was probably due to the 10 connections being single threaded and run one at a time. I then tried this:

10 timesRepeat:[[HTTPSocket httpShowPage: ''] fork].

It took about the same amount of time, but the windows started coming back quicker.

Being ambitious, I then tried the following:

100 timesRepeat:[[HTTPSocket httpShowPage: ''] fork].

And all hell broke loose. Major UI corruption. Turns out that HTTPSocket::httpShowPage is not thread safe, and updating the UI from more than one thread is a bad idea. This is fair enough – the method is basically a helper that pops a window with the contents of a url.

The offending line was this one in HTTPSocket::showPage

(StringHolder new contents: doc) openLabel: url.

Wanting a quick way to make it work for me, I went on a hunt for mechanisms to ensure thread safe UI updating and found this method on WorldState:

WorldState addDeferredUIMessage:

Changing the line in httpShowPage like so:

WorldState addDeferredUIMessage:[(StringHolder new contents: doc) openLabel: url].

And all was well. Now the multiple forked requests to httpShowPage would queue up their UI updates and play nicely together.

But thats not quite the end of the story. I now had 100 windows open, all showing the raw html from my homepage, that I had to get rid of. I could have clicked on each one individually, but I’m a developer, and this is Squeak, so after much experimentation, I came up with this:

| holders darrens |
holders := SystemNavigation default allObjectsSelect:[:anObject | anObject class = SystemWindow].
darrens := holders select:[:each | each label = ''].
darrens do: [:each | each delete].

And presto, 100 windows deleted.

The moral being that a system that describes itself and written in itself and is open to change is hugely powerful, and very pleasing to work with.