[Squeakfoundation]Ad-hoc final harvesting for 3.4

Andreas Raab squeakfoundation@lists.squeakfoundation.org
Sun, 8 Dec 2002 20:35:02 +0100


Hi Rob,

> 3) Weak message sends and conversion of the NuBlu events to use them.

Ever looked at EventMessageSet?! I did this for probably the exact same
reasons that you are using weak messages sends now. And yet, neither is
not going to solve your problems ;-(

Seriously, did you ever find the time to look closely at how this is
handled in the event stuff that I did a while back (it is now in
Croquet)?! The problem with the NuBlue (and any other event) framework
is that it does not allow the subscriber to reflect about its
subscriptions. In other words, if I have a window and a button and say:

	button on: #click send: #close to: window.

then what I say is that the button should tell the window to close when
I click on it. And of course, the button has to know the window in order
to do this. And while this is a nice first-order theory it is
problematic if we close that window by any other means (in which case we
may want to stop the subscription) and naturally, the button will hold
on to the window for the rest of its live. This is the problem which you
are trying to solve with weak references but it is conceptually wrong.

The problem is that #click is really a trigger for a method (script) in
the window which may happen asynchronously. And this script is clearly
owned by the window and not by the button and that's what all of these
event frameworks never take into account. With the model that I built
this is different (and not only in this respect ;-) Here, the subscriber
always remembers its registrations (messages) *strongly* and the
publisher always remembers the subscriptions *weakly* (by default). This
has various advantages, an obvious one being that if the subscriber goes
away so does its subscription (this is what you are trying to do with
weak refs) and the publisher is not bothered by it [*1]. However, what's
even more important is that in a case like the above, the window can
reflect about its subscriptions and cancel them if it gets closed
without having to know any "external subscriptions" (e.g., added by
someone else).

[*1] I find it _extremely_ questionable to raise an error by default
here. There may be a few applications which need to know about it but by
and large I would expect people to get really confused and say "yeah, of
course it's gone that's what it *ought* to do". For those who do it is
utterly trivial to provide a different subscription (MessageSend
subclass).

In Croquet, the above example would look like:

	window startScript: #close when: {button. #click}.

which tells the window to start the #close script when the button is
clicked. [Slight side note here: #startScript denotes an asynchronous
signal; #runScript a synchronous one. So the exact equivalent would be
"window runScript: #close when: {button. #click}" but I haven't used
synchronous signals in about a year except for debugging]. The magic is
now that the window could do something like

Window>>close
	super close. "to get rid of it"
	self stopScript: #close.

in order to cancel its "subscription" (I don't like the term in this
context but it's useful to show the similarities). Or even more
radically (and that's code I am really using):

Window>>destroy
	"I shall be destroyed. Stop all scripts"
	self scripts do:[:script| self stopScript: script].

This latter makes it impossible to have any pending references if the
window should be destroyed. But there is even more fun stuff you can do
with this. Consider that if we close the window, we want to put into the
trash and be able to get it back. The button should of course work if we
get it back. How can we solve this problem?! Well, here's one solution:

Window>>initialize
	"Set me up in a way that I will only run #close 
	scripts while I am in the world"
	"pause close script when I get out of the world"
	self pauseScript: #close when: {self. #outOfWorld}.
	"resume close when I get back in"
	self resumeScript: #close when: {self. #intoWorld}.

And this will work for any number of buttons who want to send close to
the window. All of this is only possible because the *window* knows
about the scripts (subscriptions) and not the button.

There are even more advantages to this (such as for serialization) but I
think this will get you an idea why I think that any kind of
subscription mechanism that doesn't give the subscriber access to its
subscriptions is ultimately doomed to fail - you simply cannot write
fault-tolerant code if you cannot reflect about them.

Cheers,
  - Andreas