Bug 540111, part 3: Allow IPDL actors to be managed by one of a set of possible managers. r=bent

This commit is contained in:
Chris Jones 2010-01-26 22:56:12 -06:00
Родитель eefb2c4602
Коммит d30cfaf796
4 изменённых файлов: 73 добавлений и 49 удалений

Просмотреть файл

@ -66,8 +66,8 @@ class Visitor:
def visitProtocol(self, p):
for namespace in p.namespaces:
namespace.accept(self)
if p.manager is not None:
p.manager.accept(self)
for mgr in p.managers:
mgr.accept(self)
for managed in p.managesStmts:
managed.accept(self)
for msgDecl in p.messageDecls:
@ -78,7 +78,7 @@ class Visitor:
def visitNamespace(self, ns):
pass
def visitManagerStmt(self, mgr):
def visitManager(self, mgr):
pass
def visitManagesStmt(self, mgs):
@ -249,6 +249,7 @@ class Protocol(NamespacedNode):
def __init__(self, loc):
NamespacedNode.__init__(self, loc)
self.sendSemantics = ASYNC
self.managers = [ ]
self.managesStmts = [ ]
self.messageDecls = [ ]
self.transitionStmts = [ ]
@ -268,7 +269,7 @@ class UnionDecl(NamespacedNode):
NamespacedNode.__init__(self, loc, name)
self.components = components
class ManagerStmt(Node):
class Manager(Node):
def __init__(self, loc, managerName):
Node.__init__(self, loc)
self.name = managerName

Просмотреть файл

@ -1307,7 +1307,8 @@ class Protocol(ipdl.ast.Protocol):
T=Type(self.fqListenerName()))
def _ipdlmgrtype(self):
return self.decl.type.manager
assert 1 == len(self.decl.type.managers)
for mgr in self.decl.type.managers: return mgr
def managerActorType(self, side, ptr=0):
return Type(_actorName(self._ipdlmgrtype().name(), side),
@ -2552,7 +2553,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
friends = _FindFriends().findFriends(p.decl.type)
if p.decl.type.isManaged():
friends.add(p.decl.type.manager)
friends.update(p.decl.type.managers)
# |friend| managed actors so that they can call our Dealloc*()
friends.update(p.decl.type.manages)
@ -2697,13 +2698,15 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
self.cls.addstmts([ closemeth, Whitespace.NL ])
if not p.decl.type.isToplevel():
## manager()
managertype = p.managerActorType(self.side, ptr=1)
managermeth = MethodDefn(MethodDecl(
p.managerMethod().name, ret=managertype))
managermeth.addstmt(StmtReturn(p.managerVar()))
if 1 == len(p.managers):
## manager()
managertype = p.managerActorType(self.side, ptr=1)
managermeth = MethodDefn(MethodDecl(
p.managerMethod().name, ret=managertype))
managermeth.addstmt(StmtReturn(
ExprCast(p.managerVar(), managertype, static=1)))
self.cls.addstmts([ managermeth, Whitespace.NL ])
self.cls.addstmts([ managermeth, Whitespace.NL ])
## managed[T]()
for managed in p.decl.type.manages:
@ -3015,7 +3018,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
elif p.decl.type.isManaged():
self.cls.addstmts([
StmtDecl(Decl(_actorIdType(), p.idVar().name)),
StmtDecl(Decl(p.managerActorType(self.side, ptr=1),
StmtDecl(Decl(p.managerInterfaceType(ptr=1),
p.managerVar().name))
])
if p.usesShmem():

Просмотреть файл

@ -302,11 +302,11 @@ def p_ComponentTypes(p):
p[0] = p[1]
def p_ProtocolDefn(p):
"""ProtocolDefn : OptionalSendSemanticsQual PROTOCOL ID '{' ManagerStmtOpt ManagesStmts OptionalMessageDecls TransitionStmts '}' ';'"""
"""ProtocolDefn : OptionalSendSemanticsQual PROTOCOL ID '{' ManagersStmtOpt ManagesStmts OptionalMessageDecls TransitionStmts '}' ';'"""
protocol = Protocol(locFromTok(p, 2))
protocol.name = p[3]
protocol.sendSemantics = p[1]
protocol.manager = p[5]
protocol.managers = p[5]
protocol.addManagesStmts(p[6])
protocol.addMessageDecls(p[7])
protocol.addTransitionStmts(p[8])
@ -321,13 +321,22 @@ def p_ManagesStmts(p):
p[1].append(p[2])
p[0] = p[1]
def p_ManagerStmtOpt(p):
"""ManagerStmtOpt : MANAGER ID ';'
| """
def p_ManagersStmtOpt(p):
"""ManagersStmtOpt : MANAGER ManagerList ';'
| """
if 1 == len(p):
p[0] = None
p[0] = [ ]
else:
p[0] = ManagerStmt(locFromTok(p, 1), p[2])
p[0] = p[2]
def p_ManagerList(p):
"""ManagerList : ID
| ManagerList OR ID"""
if 2 == len(p):
p[0] = [ Manager(locFromTok(p, 1), p[1]) ]
else:
p[1].append(Manager(locFromTok(p, 3), p[3]))
p[0] = p[1]
def p_ManagesStmt(p):
"""ManagesStmt : MANAGES ID ';'"""

Просмотреть файл

@ -237,7 +237,7 @@ class ProtocolType(IPDLType):
def __init__(self, qname, sendSemantics, stateless=False):
self.qname = qname
self.sendSemantics = sendSemantics
self.manager = None
self.managers = set() # ProtocolType
self.manages = [ ]
self.stateless = stateless
def isProtocol(self): return True
@ -247,23 +247,31 @@ class ProtocolType(IPDLType):
def fullname(self):
return str(self.qname)
def addManager(self, mgrtype):
assert mgrtype.isIPDL() and mgrtype.isProtocol()
self.managers.add(mgrtype)
def managedBy(self, mgr):
self.manager = mgr
self.managers = mgr
def toplevel(self):
if self.isToplevel():
return self
return self.manager.toplevel()
for mgr in self.managers:
return mgr.toplevel()
def isManagerOf(self, pt):
for managed in self.manages:
if pt is managed:
return True
return False
def isManagedBy(self, pt):
return pt in self.managers
def isManager(self):
return len(self.manages) > 0
def isManaged(self):
return self.manager is not None
return 0 < len(self.managers)
def isToplevel(self):
return not self.isManaged()
@ -596,15 +604,22 @@ class GatherDecls(TcheckVisitor):
# protocol scope
self.symtab.enterScope(p)
if p.manager is not None:
p.manager.of = p
p.manager.accept(self)
seenmgrs = set()
for mgr in p.managers:
if mgr.name in seenmgrs:
self.error(mgr.loc, "manager `%s' appears multiple times",
mgr.name)
continue
seenmgrs.add(mgr.name)
mgr.of = p
mgr.accept(self)
for managed in p.managesStmts:
managed.manager = p
managed.accept(self)
if p.manager is None and 0 == len(p.messageDecls):
if 0 == len(p.managers) and 0 == len(p.messageDecls):
self.error(p.loc,
"top-level protocol `%s' cannot be empty",
p.name)
@ -619,8 +634,8 @@ class GatherDecls(TcheckVisitor):
if not dtordecl:
self.error(
p.loc,
"destructor declaration `delete(...)' required for managed protocol `%s'",
p.name)
"destructor declaration `%s(...)' required for managed protocol `%s'",
_DELETE_MSG, p.name)
for managed in p.managesStmts:
mgdname = managed.name
@ -722,7 +737,7 @@ class GatherDecls(TcheckVisitor):
self.symtab.exitScope(p)
def visitManagerStmt(self, mgr):
def visitManager(self, mgr):
mgrdecl = self.symtab.lookup(mgr.name)
pdecl = mgr.of.decl
assert pdecl
@ -741,9 +756,8 @@ class GatherDecls(TcheckVisitor):
"entity `%s' referenced as |manager| of `%s' is not of `protocol' type; instead it is of type `%s'",
mgrname, pname, mgrdecl.type.typename())
else:
assert pdecl.type.manager is None
mgr.decl = mgrdecl
pdecl.type.manager = mgrdecl.type
pdecl.type.addManager(mgrdecl.type)
def visitManagesStmt(self, mgs):
@ -946,15 +960,14 @@ class CheckTypes(TcheckVisitor):
def visitProtocol(self, p):
# check that we require no more "power" than our manager protocol
# check that we require no more "power" than our manager protocols
ptype, pname = p.decl.type, p.decl.shortname
mgrtype = ptype.manager
if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
mgrname = p.manager.decl.shortname
self.error(
p.decl.loc,
"protocol `%s' requires more powerful send semantics than its manager `%s' provides",
pname, mgrname)
for mgrtype in ptype.managers:
if mgrtype is not None and ptype.needsMoreJuiceThan(mgrtype):
self.error(
p.decl.loc,
"protocol `%s' requires more powerful send semantics than its manager `%s' provides",
pname, mgrtype.name())
# XXX currently we don't require a delete() message of top-level
# actors. need to let experience guide this decision
@ -980,21 +993,19 @@ class CheckTypes(TcheckVisitor):
loc = mgs.loc
# we added this information; sanity check it
for managed in ptype.manages:
if managed is mgstype:
break
else:
assert False
assert ptype.isManagerOf(mgstype)
# check that the "managed" protocol agrees
if mgstype.manager is not ptype:
if not mgstype.isManagedBy(ptype):
self.error(
loc,
"|manages| declaration in protocol `%s' does not match any |manager| declaration in protocol `%s'",
pname, mgsname)
def visitManagerStmt(self, mgr):
def visitManager(self, mgr):
# FIXME/bug 541126: check that the protocol graph is acyclic
pdecl = mgr.of.decl
ptype, pname = pdecl.type, pdecl.shortname
@ -1002,7 +1013,7 @@ class CheckTypes(TcheckVisitor):
mgrtype, mgrname = mgrdecl.type, mgrdecl.shortname
# we added this information; sanity check it
assert ptype.manager is mgrtype
assert ptype.isManagedBy(mgrtype)
loc = mgr.loc