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