implementing some of OOSC concurrency ideas [was: Re:secure remote proxies ( was: Re: [ENH] bytecodePrimClass andbytecodePrimEquivalentaremessage sends. Double dispatch #== )]

Rob Withers rwithers12 at mediaone.net
Tue Jan 22 06:32:00 UTC 2002


At 05:14 AM 1/21/2002, Stephan Rudlof wrote:
>Rob,
>
>Rob Withers wrote:
> >
> > We started this thread as a result of discussions about whether identity
> > should be changes in special circumstances.  If we have two proxies, P1
> > forwards from machine L to B then to R, and P2 forwards from machine L to C
> > then to R, are they identical?   Depending on what capabilities you are
> > implementing, it may be that you _do_ wnat them to be identical.
>
>There is another level of equalness if we go to distributed programming; at
>least from a practical point of view.
>Inside one image it means that its computation is very fast, but between
>different ones? Imagine comparing a number located onto the moon with a
>number on earth, one or both proxied...

Well a number may be an extreme case - it is typically an immutable or 
passByValue object - but a car object in a distributed traffic simulation 
may be a different story.  Whether the server is close by on the Moon, or 
far away on Triton, should make no difference to the correct functioning of 
the identity operation.   If perfomance is an issue, and round-trip to 
Triton has got to be ~20 minutes, then there are probably optimizations 
that can be made.  Wonder if the real object returns it's UUID upon initial 
rendezvous, then the two proxies may want to compare identity between the 
UUIDs on the local machine.  This still requires overriding identity.


>Another point why I'm somewhat afraid of changing the semantics of #==.

Let's be clear, I am not changing the semantics of #==, at all.  All I want 
to do is modify the implementation,  in some very special cases.  The fact 
that I am unable to is the issue.   Whether I really want to or ought to is 
a different question.

> > > >  Of
> > > > course, there could be a proxy control protocol, understandable by the
> > > > proxy, but it would be better encapsulated by controlling the proxy 
> through
> > > > a Mirror.
> > >
> > >I like this idea!
> > >Different 'views' of the proxy dependent on the functionality 
> needed/wished.
> > >And with this idea you don't need language extensions for controlling
> > >visibility.
> >
> > Well, I don't know.  Not for basic functionality it seems, but there may be
> > other reasons to extend the VM and have delegation primitives.
>
>Performance?
>If we go distributed the connection seems to be more the bottleneck.

Nope, performance is a distant third requirement, unless I am doing 
something dreadful to the vm.  I was considering adding a VM supported 
ObjectHandle table.  This would be for partitioning object 
space.   Delegation comes into play when you want self sends to maintain 
the correct oject identity.  I am considering a separation of object 
identity from reference identity.  These proxies are first class references.

>
><snip>
>
> > >What about implementing some of OOSC concurrency ideas in Smalltalk?
> > >
> > >In the following I will give a very rough sketch in the spirid of OOSC.
>
> > I would have to say that the strictness of preconditions and postconditions
> > makes me nervous.
>
>It needn't!
>The crucial point here is the 'precondition interpreted as waiting
>condition' semantics for synchronization, you could leave out the other
>(postcondition, invariant) ones. And you have to realize synchronization
>somehow.

A generalized Promise architecture seems to be a better model to avoid all 
of those semaphores.   That combined with doing in process event processing.


> > It seems your last 5 points are roughly the
> > follwoing.  They are all interesting steps toward concurrency.  Two things
> > I am currently worried about are, firstly, self-sends (delegation
> > primitives solve this one)
>
>I don't understand here: if I send a message to a proxy for an object, when
>do I have a self send?

If the method that is executed for that message does a send to self, then 
what should that self be?  Should it be the target (or proxant (TM)) or the 
proxy/reference?  I think it depends actually.


> > and return values,
>
>Copy or not, where to be located if proxied, etc...

right, or 'self' whatever that means in that reciever context.


> > and secondly, deciding what
> > to do when the interspace communication gets wedged, do we fail or retry
> > every message send in the system?
>
>Good question. And *how* to fail/retry and *how* to handle these cases...

E-rights solves this with a construct I will paraphrase: 
#whenResolved:on:do:, which I would send to a Promise.  This would chain a 
return value handler and an error handler around the promise.  So using 
asynchronous sends should not be completely transparent.

carProxy := carRegistry findCarWithVIN: vin.
carStatsPromise := carProxy eventualSend gimmiCarStats.
carStatsPromise
         whenResolved:
                 [:carStats | self triggerEvent: #carStatsArrived:for: 
with: carStats with: carProxy]
         on: PromiseBroken
         do:
                 [:ex | self triggerEvent: 
#carStatsPromiseBrokenException:for: with: ex nestedException with: carProxy].

The interesting thing here, is that both the eventualSend and the 
whenResolved are async, immediate return message sends.  Execution 
continues in the program, but you have arranged for handling the response 
to your async message send in both the success case and the failure 
case.  I can guarantee that the execution of these responses occurs on your 
Process.

a shorter way would be:
carProxy := carRegistry findCarWithVIN: vin.
carStatsPromise := carProxy eventualSend gimmiCarStats.
fuelPerformancePromise := carStatsPromise fuelPerformance.



> > 1) disjoint object spaces w/ proxies
>
>Yes. For the proof of the concept inside one image this is necessary. I

Well, it is for more than just proof of concept.  Don't you want to run 
your code on my machine?

>think they are automatically disjoint for separated images already.
>But dealing with these objects ideally should feel as one object space
>everywhere. Ideally: number at the moon...

I'm not sure.  It may make sense to know that there are many object spaces 
there.


> > 2) message wrappers or instance methods.  Controlled sending
> > 3) deadlock free concurrency
>
>Message wrappers: for introducing waiting conditions together with some
>separation from the 'normal' code by using existing
>(prec/post)condition/invariant stuff.

Or messageQueues, where incoming messages are guaranteed to be evaluated on 
your Process.

> > 4) each space has it's own Processor
>
>No.
>Each space may or may not have more than one Processor: a Processor is
>exclusively responsible for computations (by calling methods in the public
>interface) on one or more objects: this guarantees not to have different
>processors acting on the same object at once, since each object has *its*
>processor.

It sounds like you are speaking of Process, here, rather than Processor.  I 
was thinking of Processor more along the lines of a Scheduler.

>But you could have more than one Processor inside the same object space.
>Don't think of cpus here, the Processor concept is abstract and Proxies and
>Processors are totally different.

Of course, but having multiple Processes brings you back to needing 
Semaphores.  yuck.


>Have I misunderstood the relation from 1) and 4) here?
>
> > 5) Polymorphism/Policied Processors for different operating environments
>
>No. Polymorphism/Policied *Proxies* for different operating environments.

Well, that too.



>The processor idea is from Meyer's OOSC2, I have roughly read the
>corresponding chapter.

Mmm, I would like to read his chapter.  Is it online somewhere?

Cheers,
Robert




More information about the Squeak-dev mailing list