--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -183,28 +183,26 @@ class GenerateProtocolHeader(Visitor):
# spit out message type enum and classes
msgstart = self.pname +'MsgStart << 12'
msgenum = cxx.TypeEnum('MessageType')
msgenum.addId(self.pname +'Start', msgstart)
msgenum.addId(self.pname +'PreStart', '('+ msgstart +') - 1')
for md in p.messageDecls:
msgenum.addId(md._cxx.id +'__ID')
- if (md.decl.type.hasReply()
- or md.decl.type.isCtor() or md.decl.type.isDtor()):
+ if md.decl.type.hasReply():
msgenum.addId(md._cxx.replyid +'__ID')
msgenum.addId(self.pname +'End')
ns.addstmt(cxx.StmtDecl(cxx.Decl(msgenum, '')))
ns.addstmt(cxx.Whitespace.NL)
for md in p.messageDecls:
ns.addstmt(generateMessageClass(md, self.injectTypedefs))
- if (md.decl.type.hasReply()
- or md.decl.type.isCtor() or md.decl.type.isDtor()):
+ if md.decl.type.hasReply():
ns.addstmt(generateReplyClass(md, self.injectTypedefs))
ns.addstmt(cxx.Whitespace.NL)
ns.addstmt(cxx.Whitespace.NL)
def visitMessageDecl(self, md):
# where we squirrel away some common information
@@ -234,18 +232,17 @@ class GenerateProtocolHeader(Visitor):
rcopy = deepcopy(ret)
rcopy.type.ptr = True
method.params.append(rcopy)
md._cxx.method = method
# the ID is used by the IPC layer only
md._cxx.id = 'Msg_%s'% (md.decl.progname)
md._cxx.nsid = '%s::%s'% (self.pname, md._cxx.id)
- if (md.decl.type.hasReply()
- or md.decl.type.isCtor() or md.decl.type.isDtor()):
+ if md.decl.type.hasReply():
md._cxx.replyid = 'Reply_%s'% (md.decl.progname)
md._cxx.nsreplyid = '%s::%s'% (self.pname, md._cxx.replyid)
def visitTransitionStmt(self, ts):
ts.state.decl._cxxname = 'State_%s__ID'% (ts.state.decl.progname)
@@ -541,16 +538,24 @@ class GenerateProtocolActorHeader(Visito
self.ns = innerns
self.ns.addstmt(cxx.Whitespace.NL)
self.ns.addstmt(cxx.Whitespace.NL)
channellistener = channelname +'::'+ channellistener
p._cxx.managertype = (
'mozilla::ipc::IProtocolManager<'+ channellistener +'>')
+ if p.decl.type.isToplevel():
+ p._cxx.routeidvar = cxx.ExprVar('mLastRouteId')
+ if self.myside is 'Parent':
+ op = '++'
+ else:
+ op = '--'
+ p._cxx.nextRouteId = cxx.ExprPrefixUnop(p._cxx.routeidvar, op)
+
inherits = [ cxx.Inherit(channellistener) ]
if p.decl.type.isManager():
inherits.append(cxx.Inherit(p._cxx.managertype))
cls = cxx.Class(self.clsname, inherits=inherits, abstract=True)
if p.decl.type.isManaged():
cls.addstmt(cxx.FriendClassDecl(
_protocolHeaderName(p.decl.type.manager.name())
@@ -732,69 +737,100 @@ class GenerateProtocolActorHeader(Visito
# implement IProtocolManager interface
if p.decl.type.isManager():
register = cxx.MethodDefn(
cxx.MethodDecl(
'Register',
[ cxx.Decl(cxx.Type('ChannelListener', ptr=1), 'aRouted') ],
ret=cxx.Type('int32'),
virtual=1))
+ registerid = cxx.MethodDefn(
+ cxx.MethodDecl(
+ 'RegisterID',
+ [ cxx.Decl(cxx.Type('ChannelListener', ptr=1), 'aRouted'),
+ cxx.Decl(cxx.Type('int32'), 'aId') ],
+ ret=cxx.Type('int32'),
+ virtual=1))
lookup = cxx.MethodDefn(
cxx.MethodDecl(
'Lookup',
[ cxx.Decl(cxx.Type('int32'), 'aId') ],
ret=cxx.Type('ChannelListener', ptr=1),
virtual=1))
unregister = cxx.MethodDefn(
cxx.MethodDecl(
'Unregister',
[ cxx.Decl(cxx.Type('int32'), 'aId') ],
ret=cxx.Type('void'),
virtual=1))
+ idvar = cxx.ExprVar('aId')
if p.decl.type.isToplevel():
- register.addstmt(cxx.StmtReturn(
- cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mActorMap'),
- '.', 'Add'),
- [ cxx.ExprVar('aRouted') ])))
+ register.addstmt(cxx.StmtDecl(cxx.Decl(cxx.Type('int'), 'tmp')))
+ tmpvar = cxx.ExprVar('tmp')
+ register.addstmt(cxx.StmtExpr(
+ cxx.ExprAssn(tmpvar,
+ p._cxx.nextRouteId)))
+ register.addstmt(cxx.StmtExpr(
+ cxx.ExprCall(
+ cxx.ExprSelect(cxx.ExprVar('mActorMap'),
+ '.', 'AddWithID'),
+ [ cxx.ExprVar('aRouted'), tmpvar ])))
+ register.addstmt(cxx.StmtReturn(tmpvar))
+
+ registerid.addstmt(cxx.StmtExpr(
+ cxx.ExprCall(
+ cxx.ExprSelect(cxx.ExprVar('mActorMap'),
+ '.', 'AddWithID'),
+ [ cxx.ExprVar('aRouted'), idvar ])))
+ registerid.addstmt(cxx.StmtReturn(idvar))
+
lookup.addstmt(cxx.StmtReturn(
cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mActorMap'),
'.', 'Lookup'),
[ cxx.ExprVar('aId') ])))
unregister.addstmt(cxx.StmtReturn(
cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mActorMap'),
'.', 'Remove'),
[ cxx.ExprVar('aId') ])))
else:
register.addstmt(cxx.StmtReturn(
cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mManager'),
'->', 'Register'),
[ cxx.ExprVar('aRouted') ])))
+ registerid.addstmt(cxx.StmtReturn(
+ cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mManager'),
+ '->', 'RegisterID'),
+ [ cxx.ExprVar('aRouted'),
+ cxx.ExprVar('aId') ])))
lookup.addstmt(cxx.StmtReturn(
cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mManager'),
'->', 'Lookup'),
[ cxx.ExprVar('aId') ])))
unregister.addstmt(cxx.StmtReturn(
cxx.ExprCall(cxx.ExprSelect(cxx.ExprVar('mManager'),
'->', 'Unregister'),
[ cxx.ExprVar('aId') ])))
cls.addstmt(register)
+ cls.addstmt(registerid)
cls.addstmt(lookup)
cls.addstmt(unregister)
cls.addstmt(cxx.Whitespace.NL)
# private members and methods
cls.addstmt(cxx.Label('private'))
channeltype = cxx.Type('Channel')
if p.decl.type.isManaged():
channeltype.ptr = True # subprotocols inherit this
cls.addstmt(cxx.StmtDecl(cxx.Decl(channeltype, 'mChannel')))
if p.decl.type.isToplevel() and p.decl.type.isManager():
cls.addstmt(cxx.StmtDecl(cxx.Decl(
cxx.Type('IDMap<ChannelListener>'), 'mActorMap')))
+ cls.addstmt(cxx.StmtDecl(cxx.Decl(
+ cxx.Type('int'), p._cxx.routeidvar.name)))
elif p.decl.type.isManaged():
cls.addstmt(cxx.StmtDecl(cxx.Decl(cxx.Type('int'), 'mId')))
cls.addstmt(cxx.StmtDecl(cxx.Decl(cxx.Type('int'), 'mPeerId')))
cls.addstmt(cxx.StmtDecl(cxx.Decl(
cxx.Type(p._cxx.managertype, ptr=1), 'mManager')))
self.ns.addstmt(cls)
self.ns.addstmt(cxx.Whitespace.NL)
self.ns.addstmt(cxx.Whitespace.NL)
@@ -821,58 +857,16 @@ class GenerateProtocolActorHeader(Visito
[ cxx.ExprLiteral.String(
'['+ self.clsname +'] '+ note),
cxx.ExprVar('stderr') ])))
block.addstmt(logif)
block.addstmt(cxx.CppDirective('endif', '// ifdef DEBUG'))
block.addstmt(cxx.Whitespace.NL)
- def injectCtorResponseHandler(block, actorHandleVar, actorObjVar):
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(actorObjVar, '->', 'mPeerId'),
- cxx.ExprSelect(actorHandleVar, '.',
- 'm'+ self.otherside +'Id'))))
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(actorObjVar, '->', 'mManager'),
- cxx.ExprVar('this'))))
- if self.p.decl.type.isManaged():
- channelvar = cxx.ExprVar('mChannel')
- else:
- channelvar = cxx.ExprAddrOf(cxx.ExprVar('mChannel'))
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(objvar, '->', 'mChannel'),
- channelvar)))
-
-
- def injectDtorResponseHandler(block, actorObjVar, actorId):
- block.addstmt(cxx.StmtExpr(
- cxx.ExprCall(cxx.ExprVar('Unregister'), [ actorId ])))
- block.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(actorId, cxx.ExprLiteral.Int(-1))))
- block.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(
- cxx.ExprSelect(actorObjVar, '->', 'mManager'),
- cxx.ExprLiteral.ZERO)))
- block.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(
- cxx.ExprSelect(actorObjVar, '->', 'mPeerId'),
- cxx.ExprLiteral.Int(-1))))
-
- calldtor = cxx.ExprCall(
- cxx.ExprVar(md._cxx.method.name),
- ([ objvar ]
- + [ cxx.ExprVar(p.name) for p in md._cxx.params ]
- + [ cxx.ExprVar(r.name) for r in md._cxx.returns ]))
- failif = cxx.StmtIf(cxx.ExprCall(
- cxx.ExprVar('NS_FAILED'), [ calldtor ]))
- failif.addifstmt(cxx.StmtReturn(valueerrcode))
- block.addstmt(failif)
-
-
if self.sendsMessage(md):
pfx = None
if md.decl.type.isRpc():
pfx = 'Call'
else:
pfx = 'Send'
mdecl = deepcopy(md._cxx.method)
@@ -913,18 +907,17 @@ class GenerateProtocolActorHeader(Visito
cxx.ExprCall(cxx.ExprVar('Register'),
[ objvar ]))))
impl.addstmt(cxx.StmtDecl(
cxx.Decl(cxx.Type('mozilla::ipc::ActorHandle'),
'__ah')))
ahvar = cxx.ExprVar('__ah')
impl.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(ahvar, '.', 'm'+ self.myside +'Id'),
- objid)))
+ cxx.ExprSelect(ahvar, '.', 'mId'), objid)))
impl.addstmt(cxx.Whitespace.NL)
elif md.decl.type.isDtor():
okcode = cxx.ExprVar('NS_OK')
failerrcode = cxx.ExprVar('NS_ERROR_FAILURE')
valueerrcode = cxx.ExprVar('NS_ERROR_ILLEGAL_VALUE')
@@ -946,26 +939,18 @@ class GenerateProtocolActorHeader(Visito
failif.ifb.addstmt(cxx.StmtReturn(valueerrcode))
impl.addstmt(failif)
impl.addstmt(cxx.Whitespace.NL)
impl.addstmt(cxx.StmtDecl(cxx.Decl(
cxx.Type('mozilla::ipc::ActorHandle'), '__ah')))
ahvar = cxx.ExprVar('__ah')
impl.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(
- cxx.ExprSelect(ahvar,
- '.', 'm'+ self.myside +'Id'),
- objid)))
- impl.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(
- cxx.ExprSelect(ahvar,
- '.', 'm'+ self.otherside +'Id'),
- cxx.ExprSelect(objvar,
- '->', 'mPeerId'))))
+ cxx.ExprAssn(cxx.ExprSelect(ahvar, '.', 'mId'),
+ objid)))
impl.addstmt(cxx.Whitespace.NL)
else: # normal message
okcode = cxx.ExprVar('NS_OK')
failerrcode = cxx.ExprVar('NS_ERROR_FAILURE')
valueerrcode = cxx.ExprVar('NS_ERROR_ILLEGAL_VALUE')
hasreply = md.decl.type.hasReply()
@@ -979,17 +964,17 @@ class GenerateProtocolActorHeader(Visito
msgctor = cxx.ExprNew(cxx.Type(md._cxx.nsid),
[ cxx.ExprVar(p.name)
for p in md._cxx.params ])
if md.decl.type.hasImplicitActorParam():
msgctor.args.append(ahvar)
if self.p.decl.type.isManaged():
- route = cxx.ExprVar('mPeerId')
+ route = cxx.ExprVar('mId')
else:
route = cxx.ExprVar('MSG_ROUTING_CONTROL')
impl.addstmt(cxx.StmtExpr(cxx.ExprAssn(msgvar, msgctor)))
impl.addstmt(cxx.StmtExpr(
cxx.ExprCall(cxx.ExprSelect(msgvar, '->', 'set_routing_id'),
[ route ])))
@@ -1035,81 +1020,47 @@ class GenerateProtocolActorHeader(Visito
# log the reply, maybe
injectLogger(impl,
cxx.ExprCast(cxx.ExprAddrOf(replyvar),
cxx.Type(md._cxx.nsreplyid, ptr=1),
static=1),
'got reply ')
- if md.decl.type.isCtor():
- injectCtorResponseHandler(impl, ahvar, objvar)
-
- elif md.decl.type.isDtor():
- injectDtorResponseHandler(impl, objvar, objid)
-
- # Async ctors dtors are handled specially: we fire off the
- # ctor/dtor message, but don't actually finalize ction/dtion
- # until the other side sends a message back to us.
- #
- # The |elif| case below adds the code to the message
- # dispather switch() statement that would have been added
- # to the |Send| method to process the response message,
- # had this been a sync/rpc message.
- elif md.decl.type.isCtor() or md.decl.type.isDtor():
- case = cxx.CaseLabel(md._cxx.nsreplyid +'__ID')
- block = cxx.StmtBlock()
- objtype = cxx.Type(
- (_protocolHeaderName(md.decl.type.constructedType().name())
- + self.myside),
- ptr=1)
- objvar = cxx.ExprVar('__a')
- objid = cxx.ExprSelect(objvar, '->', 'mId')
-
- block.addstmt(cxx.StmtDecl(cxx.Decl(
- cxx.Type('mozilla::ipc::ActorHandle'), '__ah')))
- ahvar = cxx.ExprVar('__ah')
- block.addstmt(cxx.Whitespace.NL)
+ if md.decl.type.isCtor():
+ impl.addstmt(cxx.StmtExpr(cxx.ExprAssn(
+ cxx.ExprSelect(objvar, '->', 'mManager'),
+ cxx.ExprVar('this'))))
+ if self.p.decl.type.isManaged():
+ channelvar = cxx.ExprVar('mChannel')
+ else:
+ channelvar = cxx.ExprAddrOf(cxx.ExprVar('mChannel'))
+ impl.addstmt(cxx.StmtExpr(cxx.ExprAssn(
+ cxx.ExprSelect(objvar, '->', 'mChannel'),
+ channelvar)))
- msgvar = cxx.ExprVar('msg')
- unpack = cxx.ExprCall(cxx.ExprVar(md._cxx.nsreplyid +'::Read'),
- [ cxx.ExprAddrOf(ahvar) ])
- errhandle = cxx.StmtIf(cxx.ExprPrefixUnop(unpack, '!'))
- errhandle.ifb.addstmt(cxx.StmtReturn(
- cxx.ExprVar('MsgPayloadError')))
- block.addstmt(errhandle)
-
- injectLogger(block,
- cxx.ExprCast(cxx.ExprAddrOf(msgvar),
- cxx.Type(md._cxx.nsid, ptr=1, const=1),
- static=1),
- pfx +' ')
-
- block.addstmt(cxx.StmtDecl(cxx.Decl(objtype, '__a')))
+ elif md.decl.type.isDtor():
+ impl.addstmt(cxx.StmtExpr(
+ cxx.ExprCall(cxx.ExprVar('Unregister'), [ objid ])))
+ impl.addstmt(cxx.StmtExpr(
+ cxx.ExprAssn(objid, cxx.ExprLiteral.ZERO)))
+ impl.addstmt(cxx.StmtExpr(
+ cxx.ExprAssn(
+ cxx.ExprSelect(objvar, '->', 'mManager'),
+ cxx.ExprLiteral.ZERO)))
- routevar = cxx.ExprSelect(ahvar, '.', 'm'+ self.myside +'Id')
- dcast = cxx.ExprCast(
- cxx.ExprCall(cxx.ExprVar('Lookup'), [ routevar ]),
- objtype,
- static=1)
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(objvar, dcast)))
-
- failif = cxx.StmtIf(cxx.ExprPrefixUnop(objvar, '!'))
- failif.ifb.addstmt(cxx.StmtReturn(cxx.ExprVar('MsgValueError')))
- block.addstmt(failif)
-
- if md.decl.type.isCtor():
- injectCtorResponseHandler(block, ahvar, objvar)
- elif md.decl.type.isDtor():
- injectDtorResponseHandler(block, objvar, objid)
- else:
- assert 0
-
- self.asyncswitch.addcase(case, block)
-
+ calldtor = cxx.ExprCall(
+ cxx.ExprVar(md._cxx.method.name),
+ ([ objvar ]
+ + [ cxx.ExprVar(p.name) for p in md._cxx.params ]
+ + [ cxx.ExprVar(r.name) for r in md._cxx.returns ]))
+ failif = cxx.StmtIf(cxx.ExprCall(
+ cxx.ExprVar('NS_FAILED'), [ calldtor ]))
+ failif.addifstmt(cxx.StmtReturn(valueerrcode))
+ impl.addstmt(failif)
impl.addstmt(cxx.StmtReturn(okcode))
self.cls.addstmt(impl)
self.cls.addstmt(cxx.Whitespace.NL)
# create case for this message in the big handler switch statement
if self.receivesMessage(md):
@@ -1169,17 +1120,17 @@ class GenerateProtocolActorHeader(Visito
r in md._cxx.returns ])))))
errhandle = cxx.StmtIf(cxx.ExprPrefixUnop(objvar, '!'))
errhandle.ifb.addstmt(cxx.StmtReturn(cxx.ExprVar('MsgValueError')))
block.addstmt(errhandle)
elif md.decl.type.isDtor():
block.addstmt(cxx.StmtDecl(cxx.Decl(objtype, '__a')))
- routevar = cxx.ExprSelect(ahvar, '.', 'm'+ self.myside +'Id')
+ routevar = cxx.ExprSelect(ahvar, '.', 'mId')
dcast = cxx.ExprCast(
cxx.ExprCall(cxx.ExprVar('Lookup'), [ routevar ]),
objtype,
static=1)
block.addstmt(cxx.StmtExpr(cxx.ExprAssn(objvar, dcast)))
failif = cxx.StmtIf(cxx.ExprPrefixUnop(objvar, '!'))
failif.ifb.addstmt(cxx.StmtReturn(cxx.ExprVar('MsgValueError')))
@@ -1193,57 +1144,51 @@ class GenerateProtocolActorHeader(Visito
r in md._cxx.returns ]))
failif = cxx.StmtIf(cxx.ExprCall(
cxx.ExprVar('NS_FAILED'), [ calldtor ]))
failif.ifb.addstmt(cxx.StmtReturn(cxx.ExprVar('MsgValueError')))
block.addstmt(failif)
block.addstmt(cxx.StmtExpr(
cxx.ExprCall(cxx.ExprVar('Unregister'), [ routevar ])))
block.addstmt(cxx.StmtExpr(
- cxx.ExprAssn(routevar, cxx.ExprLiteral.Int(-1))))
+ cxx.ExprAssn(routevar, cxx.ExprLiteral.ZERO)))
else:
callimpl = cxx.ExprCall(
cxx.ExprVar(pfx + md.decl.progname), [ ])
callimpl.args += [ cxx.ExprVar(p.name) for p in md._cxx.params ]
callimpl.args += [ cxx.ExprAddrOf(cxx.ExprVar(r.name))
for r in md._cxx.returns ]
errhandle = cxx.StmtIf(cxx.ExprCall(
cxx.ExprVar('NS_FAILED'), [ callimpl ]))
errhandle.ifb.addstmt(cxx.StmtReturn(
cxx.ExprVar('MsgValueError')))
block.addstmt(errhandle)
block.addstmt(cxx.Whitespace.NL)
if md.decl.type.isCtor():
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(ahvar, '.',
- 'm'+ self.myside +'Id'),
- cxx.ExprAssn(objid,
- cxx.ExprCall(cxx.ExprVar('Register'),
- [ objvar ])))))
- block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
- cxx.ExprSelect(objvar, '->', 'mPeerId'),
- cxx.ExprSelect(ahvar, '.',
- 'm'+ self.otherside +'Id'))))
+ othersideid = cxx.ExprSelect(ahvar, '.', 'mId')
+ block.addstmt(cxx.StmtExpr(
+ cxx.ExprAssn(objid,
+ cxx.ExprCall(cxx.ExprVar('RegisterID'),
+ [ objvar, othersideid ]))))
block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
cxx.ExprSelect(objvar, '->', 'mManager'),
cxx.ExprVar('this'))))
if self.p.decl.type.isToplevel():
channelvar = cxx.ExprAddrOf(cxx.ExprVar('mChannel'))
else:
channelvar = cxx.ExprVar('mChannel')
block.addstmt(cxx.StmtExpr(cxx.ExprAssn(
cxx.ExprSelect(objvar, '->', 'mChannel'),
channelvar)))
block.addstmt(cxx.Whitespace.NL)
- if (md.decl.type.hasReply()
- or md.decl.type.isCtor() or md.decl.type.isDtor()):
+ if md.decl.type.hasReply():
if not md.decl.type.hasReply():
block.addstmt(cxx.StmtDecl(
cxx.Decl(cxx.Type('Message', ptr=1), 'reply')))
replyvar = cxx.ExprVar('reply')
replymsgctor = cxx.ExprNew(
cxx.Type(md._cxx.nsreplyid),
[ cxx.ExprVar(r.name) for r in md._cxx.returns ])
if md.decl.type.hasImplicitActorParam():
@@ -1258,19 +1203,17 @@ class GenerateProtocolActorHeader(Visito
block.addstmt(cxx.StmtExpr(cxx.ExprCall(
cxx.ExprSelect(replyvar, '->', 'set_sync'),
[ ])))
elif md.decl.type.isRpc():
block.addstmt(cxx.StmtExpr(cxx.ExprCall(
cxx.ExprSelect(replyvar, '->', 'set_rpc'),
[ ])))
else:
- assert (
- md.decl.type.isAsync()
- and (md.decl.type.isCtor() or md.decl.type.isDtor()))
+ assert 0
injectLogger(block,
cxx.ExprCast(replyvar,
cxx.Type(md._cxx.nsreplyid, ptr=1),
static=1),
'replying with ')
if md.decl.type.isAsync(): # => isCtor or isDtor