Re: Simultaneous destructors

Chris Jones <[email protected]>
Newsgroups gmane.comp.mozilla.devel.dom
Message-ID <[email protected]>
Jason Duell wrote:
> On Oct 8, 7:12 am, Benjamin Smedberg <[email protected]> wrote:
>> Is the following protocol also
>> race-free and allows multiple dataavailable() calls in a row?
> 
> It looks like it to me. Hopefully the IPDL compiler will be able to
> always tell us for certain (?).
> 

Yes, per its rules (one-transition commutativity only).

>>> I agree that two-phase deletion is complicated, but (i) it's the price
>>> to be paid for race-free deletion; (ii) two-phase deletion is a kind of
>>> "IPDL pattern", like "empty subprotocols", that can be documented and
>>> copied by other protocols.
> 
> I hope so.  Right now it's starting to look like a large percentage of
> the complexity of our protocols is likely to be in getting destruction
> right.
> 

Agreed, concurrent, explicit destruction is complicated.

> There's also something gross about how much the needs of IPDL itself
> are getting inserted into the state protocols. 

Why do you say that?  These are all design decisions, IPDL doesn't 
"need" anything, it's malleable.

> It's a bit like
> writing TCP applications, and suddenly having to programmatically deal
> with incoming packets after you've already called close().  Can we
> really not make things more convenient?
> 

I'm not sure you're approaching this with the right mindset.  IPDL is 
*our* language, we get to define what's kosher and not.  So far my 
working hypothesis has been that protocols should be declared 
"race-free".  If making destruction race-free is too much of a burden, 
we can change the rules.  In fact, we're changing the rules right now, 
because the original destructor design was crap :S.

> One thing that might help a little, if we do go down this road, is the
> ability to have IPDL discard msgs in certain states.  For instance:
> 
>> state CANCELED:
>>     send dataavailable goto CANCELED;
>>     send datadone goto CANCELED;
>>     send oncanceled goto DONE;
> 
> Right now I'd have to make sure my onDataAvailable method kept some
> state variable (essentially duplicating IPDL's), so that I know to
> simply discard a packet if I'm in the CANCELLED state. 

No, you don't.  You would use your IPDL actor's state to decide what to 
do.  Referencing the race-free protocol I posted in an earlier message, 
the parent-side actor's (the one generating data) C++ code doesn't have 
to know or care about destruction, except insofar as it has to 
unregister itself from Necko notification when destroyed.

On the child side, you'd need code like:

   class ChannelChild {
     bool MaybeDie() {
        if (State() == DONE)
           SendCancel();
        if (State() == DEAD) {
           SendDestructor();
           return true;
        }
        return false;
     }

     bool RecvDataAvailable(...) {
        if (MaybeDie()) return true;

        // handle data normally

        if needToCancel {
          SendCancel()
          SendDestructor()
        }
     }

     bool RecvDataDone(...) {
        if (MaybeDie()) return true;
     }

I don't find this much of a burden on the C++ author.  Again, IMHO, 
writing the IPDL protocol is the hard work.  Once the protocol is 
written, the above pseudocode can be easily written by just looking at 
the IPDL protocol (that's what I did).

> If I forget
> this, I might try to blindly deliver packets to to data structures
> I've discarded, or something like that, and there's nothing IPDL's
> compiler could do to help catch the mistake. 

Not sure what you mean here.  IPDL won't let you write a racy protocol, 
and if your C++ code sends a bad message from a particular state, the 
IPDL-generated C++ code will blow up loudly.

> So I propose something
> like
> 
>      send dataavailable goto CANCELED DISCARD;
> 
> which tells IPDL that I know about the possibility of these msgs
> arriving in this state, but that I just want them dropped on the
> floor.
> 

I'm not much of a fan of this specific proposal, but I think this is an 
interesting approach.

I tried to emphasize in earlier messages that we *can* allow racy 
destruction sequences by changing IPDL's rules.  *If* we decide that the 
non-racy ideas we've bounced around so far are too complicated, and we 
decide that we want to allow some messages to race no matter what, then 
we can add a keyword to mark these messages as such.  I don't have a 
good idea for what that keyword should be ... maybe |hidden|?  |data|? 
|packet| (by analogy to "racy" TCP packets)?  |ghost|?  Anyways, in IPDL 
we could do something like

   protocol Channel {
     //[snip]
     ghost ondataavailable();
     //[snip]

   state NORMAL:
     send dataavailable goto NORMAL;
     send datadone goto DONE;
     recv cancel goto CANCELED;

   state DONE:
     recv cancel goto DEAD;

   state CANCELLED:
     send datadone DEAD;

   state DEAD:
     recv delete;
   };

What the |ghost| specifier would mean is that *if* the message is 
sent/received from/in a state that allows it, then it's processed 
normally.  If it's sent/received from/in a state that *doesn't* allow 
it, then it's dropped.  There are a few more requirements we'd want to 
make of |ghost| messages, but that's the general idea.

That said, I think the more important decision is whether we want to 
stick with the original plan of only admitting non-racy protocols.

Cheers,
Chris
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.