Closed
Bug 540111
Opened 15 years ago
Closed 14 years ago
IPDL: Support multiple protocol managers
Categories
(Core :: IPC, enhancement)
Core
IPC
Tracking
()
RESOLVED
FIXED
People
(Reporter: mozilla+ben, Assigned: cjones)
References
Details
(Whiteboard: [land m-c])
Attachments
(5 files)
14.10 KB,
patch
|
bent.mozilla
:
review+
|
Details | Diff | Splinter Review |
5.67 KB,
patch
|
bent.mozilla
:
review+
|
Details | Diff | Splinter Review |
2.08 KB,
patch
|
Details | Diff | Splinter Review | |
13.58 KB,
patch
|
mozilla+ben
:
review+
|
Details | Diff | Splinter Review |
16.00 KB,
patch
|
bent.mozilla
:
review+
|
Details | Diff | Splinter Review |
Per IRC discussions with cjones, I propose the following enhancement to the syntax of IPDL manager declarations: protocol PManagedByFooOrBar { manager PFoo | PBar; ... }; For the sake of motivation, imagine that the above declation occurs within the following protocol hierarchy: protocol PManagesFooAndBar { manages PFoo; manages PBar; }; protocol PFoo { manager PManagesFooAndBar; manages PManagedByFooOrBar; ... }; protocol PBar { manager PManagesFooAndBar; manages PManagedByFooOrBar; ... }; Compare the above hierarchy with the most similar one achievable without multiple managers: protocol PManagedByFooOrBar { manager PManagesFooAndBar; ... }; protocol PManagesFooAndBar { manages PFoo; manages PBar; manages PManagedByFooOrBar; }; protocol PFoo { manager PManagesFooAndBar; ... }; protocol PBar { manager PManagesFooAndBar; ... }; How much better off would we be if IPDL supported multiple managers? Consider what happens when PBarParent wants to construct a PManagedByFooOrBar actor pair. With multiple managers, the PBarParent simply calls its own SendPManagedByFooOrBarConstructor method, which may be specialized for the PBarParent case, as may PBarParent::AllocPManagedByFooOrBar. On the other side of the IPC channel, PBarChild::AllocPManagedByFooOrBar and PBarChild::RecvPManagedByFooOrBarConstructor will then be called, and they may also differ from PFooChild::AllocPManagedByFooOrBar and PFooChild::RecvPManagedByFooOrBarConstructor. Even more importantly, when the PBarParent is finally destroyed, all the PManagedByFooOrBar actors it has created will be automatically destroyed as well. For want of multiple managers, I've been using the following workaround, which seems much uglier. I declare a union type union PFooOrBar { PFoo; PBar; }; so that, when PBarParent needs to construct a PManagedByFooOrBar, it can call the following method of its manager, passing a reference to itself as an argument: bool PManagesFooAndBarParent:: SendPManagedByFooOrBarConstructor(const PFooOrBar& fob) The PFooOrBar parameter is necessary so that appropriate (PBarChild-specific) action may be taken when bool PManagesFooAndBarChild::AllocPManagedByFooOrBar(const PFooOrBar&) and bool PManagesFooAndBarChild:: RecvPManagedByFooOrBarConstructor(const PFooOrBar&) are invoked against the PManagesFooAndBarChild on the other side of the IPC channel. This PManagesFooAndBarChild actor would otherwise know nothing about which of its managed protocols requested the PManagedByFooOrBar. With multiple managers, this specialization comes for free. Without support for multiple managers, I have to simulate it. Another indispensable feature of IPDL that must be simulated in the absence of multiple managers is the automatic destruction of subprotocol actors. In my workaround strategy, a PBarParent actor must explicitly track all the PManagedByFooOrBar actors it has asked its manager to construct, or else when the PBarParent is destroyed those PManagedByFooOrBar actors will almost certainly outlive it, a violation of the conceptual relationship between PBarParent and PManagedByFooOrBar. I'm open to other workaround strategies, but I can't think of anything cleaner than implementing the multiple manager syntax directly in IPDL.
Assignee | ||
Comment 1•15 years ago
|
||
One complication arose during implementation: the |Manager()| interface. As spec'd (er, implemented) currently it doesn't make sense in the multi-manager world, so I punted on it for multi-managed protocols. This required refactoring some other code that depended on Manager(). Note that these changes won't result in any behavioral or interface changes for existing generated C++ code.
Assignee | ||
Comment 2•15 years ago
|
||
bent, I'm requesting review on all the IPDL bits because I suspect we'll end up needing to merge them into m-c and backport.
Assignee: nobody → jones.chris.g
Attachment #422793 -
Flags: review?(bent.mozilla)
Assignee | ||
Comment 3•15 years ago
|
||
Attachment #422796 -
Flags: review?(bent.mozilla)
Assignee | ||
Comment 4•15 years ago
|
||
Assignee | ||
Comment 5•15 years ago
|
||
benjamn, let me know if this is approximately the interface you expected, and/or there's more you want tested. The test is pretty slim because multi-manager didn't really add any new C++ code paths in the generated code, it's almost exclusively a front-end feature.
Attachment #422799 -
Flags: review?(bnewman)
Assignee | ||
Comment 6•15 years ago
|
||
Attachment #422801 -
Flags: review?(bent.mozilla)
Reporter | ||
Comment 7•15 years ago
|
||
(In reply to comment #1) > One complication arose during implementation: the |Manager()| interface. As > spec'd (er, implemented) currently it doesn't make sense in the multi-manager > world, so I punted on it for multi-managed protocols. This required > refactoring some other code that depended on Manager(). Note that these > changes won't result in any behavioral or interface changes for existing > generated C++ code. I'll grant that the existing Manager() interface doesn't work in the presence of multiple managers. The problem is just the indeterminacy of the return type, though; any instance of a protocol with multiple managers actually has just one of those managers, right? Would it be feasible, then, to have multiple overloaded virtual bool Manager(PManagerN** result); methods? I suppose we could instead have Manager() return a union type over the possible manager types, but that seems like overkill.
Assignee | ||
Comment 8•15 years ago
|
||
The least-gross solution I came up with was // [generated by IPDL] template<typename T> struct ManagerFunctor { virtual T operator ()(PManager1*) { } virtual T operator ()(PManager2*) { } //... }; // [generated by ipdl] template<typename T> void T WithManager(ManagerFunctor<T>* f) { // Use some home grown-RTTI (it's there already) to dispatch case PMANAGER1: return f->operator()(static_cast<PManager1*>(mManager)); // ... } But of all the schemes I could think of, it seemed less complicated to just let multi-managed subprotocols roll their own Manager() access until home-grown access gets particular nasty/verbose. How do you need to get at the manager?
Reporter | ||
Comment 9•15 years ago
|
||
(In reply to comment #8) > How do you need to get at the manager? To be honest, for my multiply-managed protocol (PContextWrapper, managed by PIFrameEmbedding or PTestShell), I don't. Is that typical? Perhaps so, since a protocol whose implementation depends on its manager should probably be split into separate protocols, one for each possible manager. As long as the Manager() method stays put for singly-managed protocols, I'll be content. PObjectWrapperChild, managed by PContextWrapperChild, needs to be able to ask its manager for the appropriate JSContext* to use, for example. The only other reason I've been using Manager() was so that PIFrameEmbeddings and PTestShells could ask their manager (PContentProcess) to construct PContextWrappers, and that indirection will go away when this bug is resolved.
Assignee | ||
Comment 10•15 years ago
|
||
(In reply to comment #9) > (In reply to comment #8) > > How do you need to get at the manager? > > To be honest, for my multiply-managed protocol (PContextWrapper, managed by > PIFrameEmbedding or PTestShell), I don't. Is that typical? Perhaps so, since > a protocol whose implementation depends on its manager should probably be split > into separate protocols, one for each possible manager. > I don't know if it's typical, but I agree that separate concrete implementations (leaf classes) for each manager is the way to go, when the manager is needed. I imagine the leaf classes sharing an abstract base (that's a subclass of the actor interface) and not having much leaf-specific code. > As long as the Manager() method stays put for singly-managed protocols, I'll be > content. PObjectWrapperChild, managed by PContextWrapperChild, needs to be > able to ask its manager for the appropriate JSContext* to use, for example. > Yup, it is. We rely on it elsewhere.
Reporter | ||
Comment 11•15 years ago
|
||
Comment on attachment 422799 [details] [diff] [review] Part 4: IPDL/C++ test of "multi-manager" feature. I would still welcome a version of the Manager() protocol for multiply-managed protocols, but the behavior on display in these tests should work for my purposes.
Attachment #422799 -
Flags: review?(bnewman) → review+
Assignee | ||
Comment 12•15 years ago
|
||
(In reply to comment #8) > The least-gross solution I came up with was > > // [generated by ipdl] > template<typename T> > void T WithManager(ManagerFunctor<T>* f) Hmm ... on second thought, this could be template<class F, typename R> R WithManager(F f) { // autogenerated dynamic dispatch case PMANAGER1: return f(static_cast<PManager1*>(mManager)); // ... } where F might be the struct shown above (sans |virtual|). This is simpler, gives better type checking of F, and eliminates virtual call crud. Though I still prefer specializing implementations on manager type ;).
Reporter | ||
Comment 13•15 years ago
|
||
By the way, these patches are working great for me (see patch in bug 541589). No longer crashing on shutdown, and much more elegant code.
Updated•15 years ago
|
Attachment #422793 -
Flags: review?(bent.mozilla) → review+
Updated•15 years ago
|
Attachment #422796 -
Flags: review?(bent.mozilla) → review+
Comment on attachment 422801 [details] [diff] [review] Part 5: Allow IPDL actors to be managed by one of a set of possible managers Looks fine to me!
Attachment #422801 -
Flags: review?(bent.mozilla) → review+
Assignee | ||
Comment 15•15 years ago
|
||
Pushed http://hg.mozilla.org/projects/electrolysis/rev/d813355607dd Pushed http://hg.mozilla.org/projects/electrolysis/rev/fffccafd827f Pushed http://hg.mozilla.org/projects/electrolysis/rev/de1a20e521f8 Pushed http://hg.mozilla.org/projects/electrolysis/rev/d7a343098058 Pushed http://hg.mozilla.org/projects/electrolysis/rev/3b8310fcc35d Don't really need these on m-c except to make backporting IPDL changes easier.
Whiteboard: [land m-c]
Assignee | ||
Comment 16•14 years ago
|
||
Pushed http://hg.mozilla.org/mozilla-central/rev/31474bd89a11 Pushed http://hg.mozilla.org/mozilla-central/rev/b8fcf1bfa808 Pushed http://hg.mozilla.org/mozilla-central/rev/8ab53a49fadf Pushed http://hg.mozilla.org/mozilla-central/rev/2353ec631528 Pushed http://hg.mozilla.org/mozilla-central/rev/26ee15150bf7
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•