Another reason I like Squeak: Introspection
Tim Olson
tim at jumpnet.com
Sun May 31 22:51:47 UTC 1998
It's wonderful that the Squeak sources are fully open and easily
browsable. But even more than that, Squeak's runtime is open to browsing
(and possible modification) through introspection.
Normally introspection is reserved for things like Debuggers, but here's
a case where I used the facility to my advantage:
I needed to FTP a fairly large file from a server. Since I was working
in Squeak at the time, I figured I would do the FTP in Squeak, writing
out the contents to a file when it was complete. A couple minutes later,
after browsing the FTPSocket sources, I had an FTP process running in the
background.
After it had been running for a bit, I realized that it would be nice to
have some sort of visual indication of the FTP progress. However,
a) I didn't want to clutter up the existing FTPSocket code with a
progress display (*), and
b) I didn't want to stop and restart the transfer, in any case.
Looking again at the FTPSocket sources, I discovered that what I wanted
was the position of the stream stored in the temporary variable
'response' in the method #getAllDataWhileWatching:
Since *everything* in Squeak is an object, including the runtime contexts
of the various running processes, I was able to do the following on the
already running ftpProc:
ctxt := ftpProc suspendedContext.
[ctxt method == (FTPSocket compiledMethodAt:
#getAllDataWhileWatching:)] whileFalse:
[ctxt := ctxt sender].
This followed up the ftpProc's context chain until it found the context
which was executing in the #getAllDataWhileWatching: method. Then, to get
the value of the 'response' temporary variable in that context, I
executed:
resp := ctxt tempAt: (ctxt tempNames indexOf: 'response').
Then all I needed to do was periodically send 'position' to the resp
stream to find out how much data had been transferred:
oldSize := newSize := 0.
'FTP status:'
displayProgressAt: (Display width - 96) @ 64
from: 0 to: ftpSize
during:
[:bar |
oldSize := newSize.
newSize := resp position.
[oldSize ~= newSize] whileTrue:
[bar value: newSize.
(Delay forSeconds: 30) wait]].
(*) after succesfully doing this, I started thinking about the
user-interface ramifications of String>>displayProgressAt: It's a handy
thing, but it puts the user at the whim of the person who coded it in,
and since it is statically associated with the method, rather than some
dynamic form of progress display control, if it isn't what the caller
wants displayed, it can't easily be modified. For example, the recent
suggestions that the automatic server update progress show the progress
of the entire transfer, rather than the individual streams.
I wonder if some form of dynamic registry for progress indication,
perhaps something like how error handling is registered, might be
something to explore.
-- tim
More information about the Squeak-dev
mailing list
|