Bug 559898: Allow (sub-)protocols to manage themselves. r=bsmedberg

This commit is contained in:
Chris Jones 2010-04-26 20:11:48 -05:00
parent 867c2c58be
commit b330eeb701
11 changed files with 316 additions and 8 deletions

View File

@ -1309,9 +1309,12 @@ def _usesShmem(p):
def _subtreeUsesShmem(p):
if _usesShmem(p):
return True
for mgd in p.decl.type.manages:
if _subtreeUsesShmem(mgd._p):
return True
ptype = p.decl.type
for mgd in ptype.manages:
if ptype is not mgd:
if _subtreeUsesShmem(mgd._p):
return True
return False
@ -2419,7 +2422,8 @@ class _FindFriends(ipdl.ast.Visitor):
# don't want to |friend| ourself!
self.visit(ptype)
for mtype in ptype.manages:
self.walkDownTheProtocolTree(mtype)
if mtype is not ptype:
self.walkDownTheProtocolTree(mtype)
def visit(self, ptype):
# |vtype| is the type currently being visited
@ -2623,6 +2627,9 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
# |friend| managed actors so that they can call our Dealloc*()
friends.update(ptype.manages)
# don't friend ourself if we're a self-managed protocol
friends.discard(ptype)
for friend in friends:
self.hdrfile.addthings([
Whitespace.NL,
@ -2664,7 +2671,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
for md in p.messageDecls:
managed = md.decl.type.constructedType()
if not ptype.isManagerOf(managed):
if not ptype.isManagerOf(managed) or md.decl.type.isDtor():
continue
# add the Alloc/Dealloc interface for managed actors

View File

@ -258,7 +258,8 @@ class ProtocolType(IPDLType):
if self.isToplevel():
return self
for mgr in self.managers:
return mgr.toplevel()
if mgr is not self:
return mgr.toplevel()
def isManagerOf(self, pt):
for managed in self.manages:
@ -267,7 +268,7 @@ class ProtocolType(IPDLType):
return False
def isManagedBy(self, pt):
return pt in self.managers
def isManager(self):
return len(self.manages) > 0
def isManaged(self):
@ -275,6 +276,10 @@ class ProtocolType(IPDLType):
def isToplevel(self):
return not self.isManaged()
def manager(self):
assert 1 == len(self.managers)
for mgr in self.managers: return mgr
class ActorType(IPDLType):
def __init__(self, protocol, state=None, nullable=0):
self.protocol = protocol
@ -971,7 +976,7 @@ class CheckTypes(TcheckVisitor):
# XXX currently we don't require a delete() message of top-level
# actors. need to let experience guide this decision
if not p.decl.type.isToplevel():
if not ptype.isToplevel():
for md in p.messageDecls:
if _DELETE_MSG == md.name: break
else:
@ -980,6 +985,12 @@ class CheckTypes(TcheckVisitor):
"managed protocol `%s' requires a `delete()' message to be declared",
p.name)
if 1 == len(ptype.managers) and ptype is ptype.manager():
self.error(
p.decl.loc,
"top-level protocol `%s' cannot manage itself",
p.name)
return Visitor.visitProtocol(self, p)

View File

@ -72,6 +72,7 @@ IPDLTESTS = \
TestRPCShutdownRace \
TestRacyRPCReplies \
TestSanity \
TestSelfManageRoot \
TestShmem \
TestShutdown \
TestStackHooks \

View File

@ -0,0 +1,24 @@
include protocol PTestSelfManageRoot;
namespace mozilla {
namespace _ipdltest {
protocol PTestSelfManage {
manager PTestSelfManageRoot or PTestSelfManage;
manages PTestSelfManage;
child:
PTestSelfManage();
__delete__();
state LIVE:
send PTestSelfManage goto DEAD;
state DEAD:
send __delete__;
};
} // namespace mozilla
} // namespace _ipdltest

View File

@ -0,0 +1,23 @@
include protocol PTestSelfManage;
namespace mozilla {
namespace _ipdltest {
protocol PTestSelfManageRoot {
manages PTestSelfManage;
child:
PTestSelfManage();
__delete__();
state LIVE:
send PTestSelfManage goto DEAD;
state DEAD:
send __delete__;
};
} // namespace mozilla
} // namespace _ipdltest

View File

@ -0,0 +1,63 @@
#include "TestSelfManageRoot.h"
#include "IPDLUnitTests.h" // fail etc.
#define ASSERT(c) \
do { \
if (!(c)) \
fail(#c); \
} while (0)
namespace mozilla {
namespace _ipdltest {
//-----------------------------------------------------------------------------
// parent
void
TestSelfManageRootParent::Main()
{
TestSelfManageParent* a =
static_cast<TestSelfManageParent*>(SendPTestSelfManageConstructor());
if (!a)
fail("constructing PTestSelfManage");
ASSERT(1 == ManagedPTestSelfManageParent().Length());
TestSelfManageParent* aa =
static_cast<TestSelfManageParent*>(a->SendPTestSelfManageConstructor());
if (!aa)
fail("constructing PTestSelfManage");
ASSERT(1 == ManagedPTestSelfManageParent().Length() &&
1 == a->ManagedPTestSelfManageParent().Length());
if (!PTestSelfManageParent::Send__delete__(aa))
fail("destroying PTestSelfManage");
ASSERT(Deletion == aa->mWhy &&
1 == ManagedPTestSelfManageParent().Length() &&
0 == a->ManagedPTestSelfManageParent().Length());
delete aa;
aa =
static_cast<TestSelfManageParent*>(a->SendPTestSelfManageConstructor());
if (!aa)
fail("constructing PTestSelfManage");
ASSERT(1 == ManagedPTestSelfManageParent().Length() &&
1 == a->ManagedPTestSelfManageParent().Length());
if (!PTestSelfManageParent::Send__delete__(a))
fail("destroying PTestSelfManage");
ASSERT(Deletion == a->mWhy &&
AncestorDeletion == aa->mWhy &&
0 == ManagedPTestSelfManageParent().Length() &&
0 == a->ManagedPTestSelfManageParent().Length());
delete a;
delete aa;
Close();
}
} // namespace _ipdltest
} // namespace mozilla

View File

@ -0,0 +1,150 @@
#ifndef mozilla__ipdltest_TestSelfManageRoot_h
#define mozilla__ipdltest_TestSelfManageRoot_h 1
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/PTestSelfManageRootParent.h"
#include "mozilla/_ipdltest/PTestSelfManageRootChild.h"
#include "mozilla/_ipdltest/PTestSelfManageParent.h"
#include "mozilla/_ipdltest/PTestSelfManageChild.h"
namespace mozilla {
namespace _ipdltest {
//-----------------------------------------------------------------------------
// Parent side
class TestSelfManageParent :
public PTestSelfManageParent
{
public:
TestSelfManageParent() {
MOZ_COUNT_CTOR(TestSelfManageParent);
}
virtual ~TestSelfManageParent() {
MOZ_COUNT_DTOR(TestSelfManageParent);
}
ActorDestroyReason mWhy;
protected:
NS_OVERRIDE
virtual PTestSelfManageParent* AllocPTestSelfManage() {
return new TestSelfManageParent();
}
NS_OVERRIDE
virtual bool DeallocPTestSelfManage(PTestSelfManageParent* a) {
return true;
}
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why) {
mWhy = why;
}
};
class TestSelfManageRootParent :
public PTestSelfManageRootParent
{
public:
TestSelfManageRootParent() {
MOZ_COUNT_CTOR(TestSelfManageRootParent);
}
virtual ~TestSelfManageRootParent() {
MOZ_COUNT_DTOR(TestSelfManageRootParent);
}
void Main();
protected:
NS_OVERRIDE
virtual PTestSelfManageParent* AllocPTestSelfManage() {
return new TestSelfManageParent();
}
NS_OVERRIDE
virtual bool DeallocPTestSelfManage(PTestSelfManageParent* a) {
return true;
}
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (NormalShutdown != why)
fail("unexpected destruction!");
passed("ok");
QuitParent();
}
};
//-----------------------------------------------------------------------------
// Child side
class TestSelfManageChild :
public PTestSelfManageChild
{
public:
TestSelfManageChild() {
MOZ_COUNT_CTOR(TestSelfManageChild);
}
virtual ~TestSelfManageChild() {
MOZ_COUNT_DTOR(TestSelfManageChild);
}
protected:
NS_OVERRIDE
virtual PTestSelfManageChild* AllocPTestSelfManage() {
return new TestSelfManageChild();
}
NS_OVERRIDE
virtual bool DeallocPTestSelfManage(PTestSelfManageChild* a) {
delete a;
return true;
}
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why) { }
};
class TestSelfManageRootChild :
public PTestSelfManageRootChild
{
public:
TestSelfManageRootChild() {
MOZ_COUNT_CTOR(TestSelfManageRootChild);
}
virtual ~TestSelfManageRootChild() {
MOZ_COUNT_DTOR(TestSelfManageRootChild);
}
void Main();
protected:
NS_OVERRIDE
virtual PTestSelfManageChild* AllocPTestSelfManage() {
return new TestSelfManageChild();
}
NS_OVERRIDE
virtual bool DeallocPTestSelfManage(PTestSelfManageChild* a) {
delete a;
return true;
}
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (NormalShutdown != why)
fail("unexpected destruction!");
QuitChild();
}
};
} // namespace _ipdltest
} // namespace mozilla
#endif // ifndef mozilla__ipdltest_TestSelfManageRoot_h

View File

@ -20,6 +20,8 @@ IPDLSRCS = \
PTestRPCRaces.ipdl \
PTestRPCShutdownRace.ipdl \
PTestSanity.ipdl \
PTestSelfManage.ipdl \
PTestSelfManageRoot.ipdl \
PTestShmem.ipdl \
PTestShutdown.ipdl \
PTestShutdownSub.ipdl \

View File

@ -0,0 +1,8 @@
protocol manageSelfToplevel {
manager manageSelfToplevel;
manages manageSelfToplevel;
child:
manageSelfToplevel();
__delete__();
};

View File

@ -0,0 +1,10 @@
include protocol manageSelf_Toplevel;
protocol manageSelf {
manager manageSelf_Toplevel or manageSelf;
manages manageSelf;
child:
manageSelf();
__delete__();
};

View File

@ -0,0 +1,9 @@
include protocol manageSelf;
protocol manageSelf_Toplevel {
manages manageSelf;
child:
manageSelf();
__delete__();
};