Lots of concurrency

Stephen Pair spair at advantive.com
Tue Oct 23 20:42:57 UTC 2001


I view call/return as a specialized form of concurrent (asynchronous)
messaging.  You are sending a message, waiting for it to complete, and
then potentially doing something with a result that is given back to
you.  But, it would definitely be nice to have this system implemented
on top of a concurrent one (and perhaps optimized for performance).  I
would certainly make a lot of simulations easier to construct.

A long time ago, I did an experiment with asynchronous message sending
(see http://www.advantive.com/squeak for the code) where you could have
any number of people catching and throwing baseballs with one another.
A shared queue represented a uni-directional path between any two
people.  I implemented a syntax that looked like "anObject asend
someMessage" to actually do the asynchronous messaging.  It was very
neat to simply inject a baseball into one of the queues and see (via the
transcript) the players start catching and throwing the baseball between
each other.  You could also inject multiple baseballs (oh, and they were
good baseball players because they never dropped any of the baseballs).
I never created any morphs of the players, but it was neat anyhow.

I could have created this simulation with the base Squeak Process and
synchronization code, but the implementation of asynchronous messaging
made the simulation extremely simple to create.  I didn't have to worry
about creating or forking processes and all of that nonsense.

In this scheme messages sent asynchronously replied immediately with an
"answer queue (a SharedQueue)".  The results (which there could be zero,
one, or more) would appear in the answer queue.  If you needed the
result of a particular message, you just plucked out of this queue.  So,
the implementaion of #catchAndThrowBaseballs: would use the argument for
the input queue of baseballs, and would throw baseballs by putting them
into its answer queue (by repeatedly saying (thisContext answer:
aBaseball).  The player would continuously catch and throw baseballs
until you told him to be tired.  You linked up the players by calling
#catchAndThrowBaseballs: with the answer queue from some other call to
#catchAndThrowBaseballs:.

Asynchronous messaging made the simulation simple to construct in that I
didn't have to worry about making sure (via forking and such) that the
participating objects could go about their business independently.

The events in this scheme were the Semaphore's triggered by the
SharedQueues.  This is a good bit simpler and more limited than a scheme
where an object polls it's environment periodically for events.  In
morphic, it would be nice to allow for morphs to easily detect objects
in their proximity, but this is not the only thing we might need to
detect.  

As I see it, asynchronous messaging is pretty easy (maybe not a
primitive implementation or a well-performing implementation, and there
are some issues about language syntax that need some thinking).  I see
the problem of a generalized event detection scheme being the harder
problem to solve.  Currently, the stepping in morphic happens based on a
requested step interval, but if the system is overloaded to the point
where these intervals cannot be honored, the simulation can become
inaccurate (unstable) if these stepping methods are not carefully
written.  Do we need some ability to use these step intervals as a sort
of frequency not necessarily tied to real time, but rather relative to a
frame of the simulation?  Then wouldn't the simulation itself, when
burdened by a lot of processing, slow down, but not deteriorate?

- Stephen


-----
Ken kahn wrote:

"The basic principle of recursive design is to make the parts have the
same power as the whole" rather than dividing the computer into "lesser
stuffs", like data structures and procedures, we should divide it into
lots of little computers that communicate together.

I want to take this literally. Think of an object as a little computer.
Except maybe when an object sends a message to self, all message sending
is to another computer and therefore should be "eventual" -
computer/objects shouldn't hang just because the object they are sending
a message to isn't currently ready. (Bye bye call/return.) When a
computer/object creates a new computer/object the newly created object
becomes completely independent. If there is any sequentiality in the
execution of a method it is minor. If the method sends 3 messages and
creates 2 new objects then the order those things happen doesn't matter.
-----





More information about the Squeak-dev mailing list