Smalltalk IO

Continuing on my own personal Smalltalk Renaissance, I spent some time investigating threading, IO, and general long-running operations. First a small rant. There is a woeful lack of documentation out there on how threading works (or doesn’t) in Smalltalk. The stuff I did find did not fill me with confidence, as it seemed to indicate that Smalltalk was inherently single-threaded, and thus crippled when it comes to doing network IO. In the end I decided to just try it. This is what I came up with:

| httpClient request response |
httpClient := HttpClient new.
request := HttpRequest get: 'http://www.cincom.com'.
Transcript show: 'Before Request'; cr.
response := httpClient executeRequest: request.
Transcript show: 'Request Complete'; cr.
Transcript show: response body decodedValue.
Transcript show: 'After Request'; cr.

Sure enough, the whole environment froze while waiting for the request to complete. Game over.

Then I finally decided to actually look at the core libraries, and happened upon the BlockClosure class, with the promising looking ‘fork’ method. Hmm. My second attempt looked like this:

| httpClient request response |
httpClient := HttpClient new.
request := HttpRequest get: 'http://www.cincom.com'.
Transcript show: 'Before Request'; cr.
[
response := httpClient executeRequest: request.
Transcript show: 'Request Complete'; cr.
Transcript show: response body decodedValue.
] fork.
Transcript show: 'After Request'; cr.

Note the addition of the [ ] around the code that actually hits the network. This denotes a block, which is in fact an instance of BlockClosure, which brings the ‘fork’ method call into play. Sure enough, the second attempt did not freeze the whole environment, and I saw ‘Before Request’ immediately followed by ‘After Request’ in the system transcript. Shortly followed by the html from Cincom’s homepage.

Smalltalk rocks.