[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: x2AnyChannels do not allow alting


First something Gerald mentioned:

> Unfortunately, this technique is not bullet-proof. A *2OneChannel channel
> can still be used by multiple ALTs and the compiler accepts it without
> complaining.

This is not an ALT-specific problem.  The problem is one of channel useage
checking - something we take for granted from occam compilers!  occam can
get these things checked because channels are not data-types and the compiler,
therefore, knows that some special rules apply to them (e.g. no multiple
readers) and can enforce it.

Becuase Java is not CSP-aware and we are building in CSP primitives with
a *library* (and not a *language*) mechanism, the Java compiler can perform
no special checks in regard to channel useage - a Channel is just another
class (interface actually in JCSP).  Now, we could build a tool to do those
checks for JCSP or CTJ - but that tool would have to be tied to recognise
specific user names (like One2OneChannel).  But then it could complain about
a One2OneChannel that was written to by two or more processes - after a bit
of chasing through source files.

Meanwhile, if you set up a network with two or more readers reading from
a *2OneChannel, there is race hazard disaster looming.  So, it's up to the
JCSP user not to do that - i.e. it's a design rule.  If those two or more
readers happen to ALT (as well as read) from a *2OneChannel, another race
hazard lurks but we were doomed anyway!

Of course, if this worries you, dispense with all varieties of channel apart
from Any2AnyChannel (like CTJ).  Then, multiple readers and multiple writers
are always safe - unless, of course, as Gerald points out, any one of those
readers tries an ALT on that channel ... then, it's back to race hazards!

But in JCSP, I prefered to offer the user a variety of 1-*, *-1 and *-*
channels.  This lets the designer document how he/she intends to use the
channel (and a tool - but not the compiler - could verify this).  Another
benefit is that the application suffers only the synchronisation overheads
it needs.  Another *benefit* (and this gets back to Marcel's question) is
that once you have declared a 1-* or *-* channel, the compiler will not
allow a reader to ALT on it.  As Gerald notes:

> This restriction in JCSP should prevent two or more competing ALT constructs
> on a shared channel. This is because competing ALT constructs are a source
> of hazardous race conditions.

So, in JCSP, you expose yourself to a channel race hazard if and only if you
deliberately set more than one process to work at the end of a channel that
has been declared for use by only one.

Marcel asks:

> This is quite a restriction.  I can imagine that the following
> (less demanding) restriction is also sufficient:
>   If an ALT selects an *2AnyChannel, the process has to perform
>   an input from that channel.
> Is this correct?

No - that is not sufficient.  The above is the rule is any case.  In occam,
the selection of the ALTernative and the execution of the guard are atomic.
In JCSP, the select (priSelect or fairSelect) just returns an index and you
are *obliged* to input from that channel (if the index corresponded to
a channel).  The compiler will let you not do so - but, in that case, you are
not playing the game and nasty things will happen.  Again, these rules could
be checked by a tool that knows about all these special names (`Alternative',
`select' etc.).  [Note: JCSP could have chosen to make the selection and input
(in the case of a channel) atomic: make the `select' method do the input and
return the received object *and* the selection index.  But the Java language
doen not provide a neat way of returning an object *and* and int from a method
:-( ...]

> If my suggestion is incorrect, I would like to know why...

The occam3 SHARED channel reflects a fair-ALT over an array of channels where
no preconditions may be set and we never need to do any other kind of input
from that array (e.g. to do a ALTing read from a subset of them).  The SHARED
channel also enables a unit-time implementation of this restricted ALT.
The Any2OneChannel does this for JCSP.

The *2Any channel does this for readers.  In effect, the channel is ALTing
over attempted outputs to each of those readers - i.e. there are output
guards.  It follows, therefore, that allowing any of those readers also
to ALT over a channel input is *either* going to be unsafe (there will
be a race hazard disaster sometime) *or* there needs to be a complex and
time-consuming policing action to sort things out.  That's why output
guards are not allowed in occam (nor in JCSP).

So, JCSP *could* be amended so that *2AnyChannels extend the Guard interface
and could, therefore, be used as guards in ALTs.  But the implementation of
those guard methods (enable/disable) and the triggering write method of the
*2AnyChannel itself would be frightening!  It's been hard enough already
making the JCSP Alternative free of race hazards - and we still haven't
proved it (although we now have the machinery to do so).

So, do we really need to allow a server, competing with other servers for
the same channel, to back off?  One view of an Any2AnyChannel is for clients
and servers to find each other - so long as they don't care how they are
matched up.  Each client (the writer to the Any2AnyChannel) and server
(the reader) commits to this pairing.  A neat thing to do is for the client
to send a private One2OneChannel down the Any2AnyChannel.  When the Any2Any
communication has happened, they can commune away in private!

If we really need to withdraw a server's offer of service, get a proxy to
commit to the Any2AnyChannel read and output details to the server (who can
handle the rest of the transaction).  The server can safely ALT out of
taking the input from its proxy.  The proxy may get stuck but who cares?

Of course, the above would be much better for an occam with ANY.ANY.CHANs,
where the cost (run-time + memory) of the proxy would be zilch ...

I do have other uses of Any2AnyChannels, particularly if they are buffered.
They make a secure buffered pool in which any processes in a parallel network
may deposit and retrieve items.  If you are working with passing objects around
the network and obey the rule of send-it-and-lose-it, all is well.  But we
need a source for empty objects and a sink.  A buffered Any2AnyChannel gives
this for free!  Again, for this application, I don't need the competing
object grabbers to back off - they just have to wait and that's OK!!

Does anyone have an example where a process, competing with other processes,
needs to back off that competitive read?