Logical processes
The Smalltalk execution model is dominated by synchronous message sending. An object sending a message waits for the result to be returned before processing the next expression. Normally this execution takes place in one Smalltalk process. With the introduction of remote references however, a message send can result in a remote message to a completely different Smalltalk image. As a result, the Smalltalk process running the request will necessarily be different from that of the sender.
Assuming that the sender blocks waiting for the reply, this does not break the superficial execution semantics. However, difficulties do arise in situations involving user interface-driven code, exceptions, debugging, out-of-scope returns and transactions. In these cases, extra data is implicitly or explicitly attached to the process running the code. For example, an exception handler installed in the sending process would not be available for the remote process.
SST addresses this using logical processes. Logical processes maintain typical process attributes (such as error handlers) across many actual (distributed) processes. When a process sends a remote message its relevant state, but not the stack itself, is captured and forwarded to the receiving process. This state is used to make the receiving process seem like the originating process.
In addition, the Smalltalk execution model ensures that each logical process be implemented by at most one physical process per object space. That is, if some object O running in process P sends a message M to a remote object R and in the processing of M a message N is sent back to the space containing O, N will be executed by process P.
Consider the ping-pong application--two objects, Ping and Pong, on different machines continually send messages back and forth. If you run the SstPingPongByReference example you will notice that the process information printed in the Transcript for each request is different. That is, each request is being handled by a different physical Smalltalk process even though they are part of the same logical call chain (that is, Ping pings Pong, Pong pongs Ping, and so on). If you run the SstPingPongLP example, notice that the same process is being used to handle successive requests in the ping-pong chain.
In the figure below, the black line running through the boxes represents a physical Smalltalk process on the different machines. The gray line represents the logical process, which combines the two physical processes to form a single logical process. Note that
pong:with: is being executed in the same physical process as
start:with:.
The examples in subclasses of SstPingPongLP demonstrate how logical processes maintain the normal Smalltalk process semantics with respect to termination, out-of-scope returns and error handling. For example, if ping:with: in the above figure had an ifCurtailed: statement and pong:with: terminated its local process, the ifCurtailed: block would run, according to Smalltalk execution semantics. But the block is defined in a different physical process on a different machine (see SstPingPongLPTerminate). The situation is similar for out-of-scope returns (see SstPingPongLPUnwind). Logical processes arrange for these semantics to be preserved.
Logical processes also make it possible to build a distributed debugger which follows call chains as they hop from space to space. All operations such as step-into, step-over, and drop-to-frame are supported.
The logical process model is independent of the interconnection mechanisms used to communicate but only works fully if all object spaces involved in an interaction are SST spaces with logical processing enabled. If some computation crosses into a space which does not support logical processes, the system does not fail. Rather system capabilities degrade gracefully to the level which is supported by that space. With the distributed debugger, for example, you will not be able to debug a computation once it crosses into a non-logical process space.
Last modified date: 09/19/2018