Peter Van Roy wrote:
> David Hopwood wrote:
> 
>>> In the case of threads, the original version of Oz, Oz 1, created
>>> threads implicitly.
>>> After some time we saw that this was the wrong decision.  For example,
>>> it makes reasoning about termination much harder.  Again and again, we
>>> learned the lesson that making things explicit is the best solution:
>>> state, threads, laziness, search.
>>
>> Perhaps this conclusion should be extended to explicit waiting on
>> dataflow variables ;-)
>
> I don't think so.  Just the opposite: [explicitly waiting on dataflow
> variables is actually the more complicated thing].

The kernel language and its semantics are not significantly more or less
complicated.

Whether programming in the full language with explicit waits is more
complicated is a matter of what you're used to. Yes, you have to write
slightly more code with explicit waits. But that code is straightforward,
and it makes turn boundaries explicit. This is just like making threads or
other features explicit: you have to write slightly more code, but that
code is easier to reason about.

How is it easier to reason about, you may ask?

Most importantly, it is easier to reason about the atomicity, consistency
and isolation of state updates. Immediate calls that are performed in the same
"turn" are guaranteed not to be interleaved with calls from other vats. That
is, the side effects of a turn form a kind of transaction -- but one that is
lightweight enough to be used routinely.

In terms of ACID properties (http://en.wikipedia.org/wiki/ACID), strictly
speaking these lightweight transactions only *guarantee* the Isolation
property (in its strongest form: serializable isolation). Atomicity and
Consistency can't be automatically guaranteed at this level, at least not
without much greater overhead and complexity. However isolation is a
prerequisite for writing code that manually ensures atomicity and consistency.
Durability is dealt with by other mechanisms in E.

(Although this behaviour could be partially simulated in other message
passing models by combining each sequence of methods that needs to be
isolated into a single method, that simulation is inadequate because it
requires changing the target object by adding boilerplate code, and
because it doesn't work for groups of objects.)

Note that in cases where a task written in E needs the results of several
promises, the implementation of the task will not necessarily leave it
until the last moment when a given promise is used to wait for its
value. In general, it will split the task over several turns, where each
turn that needs a given set of variables is isolated from the point
of view of other vats. Because the waits are explicit, the programmer is
encouraged to think about where the boundaries between turns should be,
i.e. what intermediate states should be observable.

It is also very easy to reason about when programs can wait, which is
important in interactive, distributed, and real-time applications (although
E is not suitable as a hard real-time language as it stands).

I am not arguing that E gets this absolutely right, BTW, at least not in its
current implementation. It could do with better support to help the programmer
to keep track of which references are resolved, which are near (i.e. in the
same vat), etc. E was intended to support soft typing, which could provide
this information, but the compile-time part of this is not yet implemented.

[to be continued...]

-- 
David Hopwood <[EMAIL PROTECTED]>


_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to