Remote Data Structure Editor Each region corresponds to an address, represented as a container and a key. Containers and keys are opaque objects, represented as a name in the form of "&123" (they just have to be unique, no special reason for this form 'cept it looks neat). The Opaque object dictionary maps the &123 names to dictionaries, describing the remote objects. These dictionaries could be subclasses of Selection. The opaque selections could contain such things as the type of the object, a socket file to the remote server where the opaque object lives, a user token number corresponding to the object in the remote server, the object's printable representation, a cached copy of the object, a list of active views (to be notified when the object changes), unique ID's (interest /Action CID's?) mapped to interests in outstanding replies on the object (so replies can use deliverevent). PostScript code is sent both ways over the socket. There should be a monitor around writing to the file, but not around waiting for results. Results are delivered thought the event queue. There is a dedicated process "cvx exec"'ing each end of the socket. (The connection should be symetric.) Each process defines user tokens for the objects in its address space that the other process has opaque references to. When a PostScript process wants to perform a remote operation on an opaque object that returns results, it must send PostScript commands down the socket (in a monitor), and wait for a reply through the event queue (not in a monitor). There is a utility function for making remote procedure calls, which takes an opaque object (name), a procedure to execute remotely (taking one arg (the object) and returning one result), and a procedure to execute locally (put in the interests callback, taking one arg (the result)). /RPC { % => (expresses interest) createevent begin /Name 4 -1 roll def % remote local UniqueID % remote local id % Stash action=>interest mapping in opaque selection dict. Opaque Name get 1 index currentdict put /Action 1 dict def Action 3 1 roll exch % remote dict id local put % remote currentdict expressinterest Opaque Name get % remote dict end begin % remote SocketLock { Socket exch SendCode % } monitor end } def /SyncRPC { % opaque remote => result % The local proc quits with the result on the stack, % returning it to waitprocess. { { /ClientData get quit } RPC awaitevent } fork waitprocess % opaque remote result exch pop exch pop } def /SyncRPCTimeout { % timeout default opaque remote => result / default { { /ClientData get quit } RPC % timeout default % XXX: express timeout interest with callback that pops event, % pushes default, then quits. awaitevent } fork waitprocess % opaque remote result exch pop exch pop } def