Hah!
I think I get it!
Your comments about asynchronicity were the key.

Rewriting now.....



----- Original Message -----
> 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