On Tue, Mar 5, 2013 at 1:50 PM, Michael Goulish <mgoul...@redhat.com> wrote:

>
>
> ----- Original Message -----
> > On Tue, Mar 5, 2013 at 3:20 PM, Rafael Schloming <r...@alum.mit.edu>
> > wrote:
> > > On Tue, Mar 5, 2013 at 11:33 AM, Rajith Attapattu
> > > <rajit...@gmail.com>wrote:
> > >
> > >> On Tue, Mar 5, 2013 at 2:24 PM, Ted Ross <tr...@redhat.com> wrote:
> > >> >
> > >> > On 03/05/2013 02:14 PM, Rajith Attapattu wrote:
> > >> >>
> > >> >>
> > >> >> This is a good explanation that we need to put in the docs, as
> > >> >> Application developers certainly need to know how it behaves.
> > >> >> If one were to use the current C impl, it certainly gives the
> > >> >> impression that put() is meant to write messages into your
> > >> >> internal
> > >> >> buffer and send() will actually write it to the wire.
> > >> >> Unfortunately some applications will depend on this behaviour,
> > >> >> even
> > >> >> though it's not advisable
> > >> >>
> > >> >> If we are to change from say #2 to #1 or even #3 we need to
> > >> >> release
> > >> >> note it prominently.
> > >> >>
> > >> >> I think the best solution is to make this behaviour
> > >> >> configurable, and
> > >> >> advertise the default very prominently.
> > >> >> This way application developers will know exactly what they are
> > >> >> getting instead of us making changes underneath.
> > >> >>
> > >> >> Rajith
> > >> >>
> > >> >
> > >> > Making this configurable multiplies the size of the test matrix.
> > >> >  Can't
> > >> we
> > >> > make this simpler?
> > >>
> > >> I do understand your concern here, but the Java impl already does
> > >> both
> > >> #1 and #2 and Rafi wants to do #3 in the future.
> > >> The old JMS client does something similar.
> > >>
> > >> I agree that if we just do option #2 (as you suggest below), then
> > >> the
> > >> application can easily do #1 and #3 on top of that.
> > >> But I'm sure they will like if the library implements those
> > >> strategies
> > >> for them and they have the ability to pick a strategy.
> > >>
> > >
> > > I don't  see why we'd make this configurable. All three options
> > > actually
> > > fit the same general semantics. Even if you're optimistically
> > > trying to
> > > transmit every single time put is called it's entirely possible for
> > > the
> > > socket to be blocked every single time you try. If this were to
> > > happen the
> > > implementation of #1 would appear to behave precisely the same as
> > > #2
> > > behaves.
> > >
> > > In other words if you're coding correctly against the API you can't
> > > assume
> > > that put will or won't have transmitted anything regardless of
> > > which
> > > strategy is used internally.
> > >
> >
> > I agree with you. You make a very good point.
> > Perhaps we should explicitly make that clear in our docs to avoid
> > applications written against wrong assumptions.
>
>
> I can certainly do that, but it seems to me that semantics should be
> simple, obvious, and orthogonal.
>
> What seems non-simple and non-obvious to me so far is:
>
>   put() might send, or not.  It doesn't send now, but it
>   might later.
>

This behaviour is fundamental to an asynchronous API. You're not actually
doing things, you're scheduling things to be done asynchronously. This is
why put() returns a tracker so you can come back and check on the status of
your asynchronous operation.

  recv() can cause messages to be sent.
>
>   send() can cause messages to be received.
>

I don't think that's a correct way of describing what is going on. You
scheduled an asynchronous operation via put(). That means it can occur at
any point later on. The fact that it happens to be trigger by the recv() in
the example I gave is simply because recv() is blocking waiting for the
reply and so it is inevitably going to end up blocking until the request is
sent because the reply won't be triggered until after the request is sent.

As for send(), it's simply inaccurate to say that send causes messages to
be received. Messages can be spontaneously sent by remote parties at any
time (given sufficient credit has been previously granted). What caused
them to be received is the other party actually sending them, and if
message data happens to arrived while we're inside a call to send(), we
can't simply throw those messages away, so they go onto the incoming queue
just as if they had arrived during a call to recv().


> I would think that
>
>   1. every verb should only mean one thing
>
>   2. there should be a simple mental model,
>      against which every verb performs a
>      predictable action.
>
> so for example:
>
>   put    ( messenger, message );     // enqueue for sending
>   send   ( messenger, BLOCK );       // block till all sent.
>   send   ( messenger, DONT_BLOCK );  // send what you can.
>   credit ( messenger, 10 );          // limit incoming queue size
>   recv   ( messenger, BLOCK );       // block till I get a message
>   recv   ( messenger, DONT_BLOCK );  // if no messages incoming, return.
>

I'm not sure how your example is meaningfully different from the current
API. Your short descriptions are only positive. If you intend to "simplify"
by allowing one and only one action per call then you need to document that
recv prevents messages from being sent, and send prevents messages from
being received.

Regardless I think you may be missing an asynchronous component from your
mental model. Events can happen spontaneously, such as messages being
sent/received over the wire, but that doesn't invalidate the semantics of
send as "block until all the messages are sent" or recv as "block until
there is a message to get". The only thing we've been discussing is the
granularity of that asynchronousness. One extreme is a fully lazy
implementation that never bothers doing any asynchronous work until it has
to block for something. At the other end of the spectrum is an
implementation with a background thread that constantly tries to do any
outstanding work. For both these implementations though (and any in between
implementations) the programming semantics are identical: "put" is
requesting that a message be asynchronously sent, and send/recv are
blocking until a specific condition is met.

--Rafael

Reply via email to