At Deep Into Smalltalk at Lille in March Noury Bouraqadi presented a simple example of remote messaging. (The exampes are here http://car.mines-douai.fr/noury/docs ).
You have two images. One is a proxy; the other is the server. You send a message to the proxy and it appears on the Transcript of the server.
proxy := Proxy newOnPort: 5432. proxy cr; show: 'This is my boomstick!'.
So you send a message to Proxy, which understands absolutely nothing. Zilch. It defaults to #doesNotUnderstand:, which captures the message as an instance of Message.
doesNotUnderstand: *aMessage* "Message answer is not handled!" | messageBytes | *aMessage* lookupClass: nil. messageBytes := ReferenceStream streamedRepresentationOf: *aMessage*. socketStream := SocketStream openConnectionToHostNamed: 'localhost' port: portNumber. socketStream isConnected ifFalse: [^nil]. [socketStream sendCommand: messageBytes] ensure: [socketStream close].
You can see here that it is serialized by ReferenceStream, shot over the wire by SocketStream. It is de-serialized here in the server image:
dispatch: messageBytes | message | *message* := ReferenceStream unStream: messageBytes. *message* sendTo: Transcript
The important part is the last line, which has the Message instance sent #sendTo: and so for all intents and purposed you have send this old standby:
Transcript show: 'This is my boomstick!'
except the Transcript is not yours; it's somebody else's.
Now let's look at Croquet/Qwaq FarRef>>#doesNotUnderstand: which has a class comment that says:
"I represent a reference to an object living on another island. When I receive a message I pass the message on to the object."
The class FarRef looks to me to be the same as Noury's Proxy: it understands no selectors; it uses a #doesNotUnderstand: override to capture the message; and, sends the message over the wire.
The implementation of #doesNotUnderstand: is not clear to me, so I'll stick to the class comment as my proof. Does Qwaq use ReferenceStream to serialize? I don't know.
In Spoon we have Other>>#doesNotUnderstand: which has this class comment:
"Each of my instances respresents an object in another memory, reachable through a NetStream. Messages sent to one of my instances are forwarded to the remote object, and another Other is answered."
It has #doesNotUnderstand: with a simple #forward: selector
doesNotUnderstand: aMessage ^self forward: aMessage
and then:
forward: aMessage "Forward aMessage to the remote object I represent, and answer the result." "This message was invoked by the virtual machine, in response to an attempt to send aMessage to me."
"Transcript cr; print: aMessage; endEntry." ^( ReflectiveBehavior at: aMessage selector ifAbsent: [ ^OutgoingMessageExchange forward: aMessage for: remoteIdentity over: session] ) value: session value: aMessage arguments
I think Craig may be familiar with the idea of a remote Transcript as he's included a class comment there that looks like Noury's simple program. The message gets passed to OutgoingMessageExchange. Does it use ReferenceStream to serialize? I don't know yet.
To conclude, each of these different programs creates a proxy that understands no selectors, but uses #doesNotUnderstand to glean the message. Thus captured it sends it to a remote receiver.
This is the beachhead I've needed to understand Spoon. I'll extend outward from this observation.
Chris
Hi Chris--
Sorry for the delay in responding to your messages, I'm getting over a bad flu.
Spoon normally doesn't use >>doesNotUnderstand:. Among the Spoon VM changes is a modified method lookup routine, which treats proxies specially, sending >>forward: directly. See Interpreter>>lookupMethodInClass:.
The minimal images (subject and history) have Smalltalk-level code that takes advantage of that VM change. However, the headful image in Spoon 3a3 (whose code you cited) uses an initial remote-messaging adaptation for Squeak 4.2, that I wrote to be compatible with the stock VMs. In retrospect, it wasn't worth the confusion; sorry about that.
Spoon's remote messaging support doesn't use ReferenceStream to serialize, it uses a minimal proxy-aware framework (with a bias toward sending references, not copies). See class MessagingSession, and the implementors of storeOnProxyStream:for: and storeOnProxyStream:.
Thanks for bearing with me as I improve the class and method comments!
-C
-- Craig Latta www.netjam.org/resume +31 6 2757 7177 + 1 415 287 3547
spoon@lists.squeakfoundation.org