Bug 506075: eliminate handshaking async constructor protocol, use smarter routing ID assignment
authorChris Jones <jones.chris.g@gmail.com>
Fri, 24 Jul 2009 18:24:27 -0500
changeset 35812 9e528a72d1dd303865c3537f66b70314218fd348
parent 35811 ead78e10f2252d2229ce08575f9ef3e60969c230
child 35813 9969da8c718a88e7f97d2422288c21f42c7c4a64
push idunknown
push userunknown
push dateunknown
bugs506075
milestone1.9.2a1pre
Bug 506075: eliminate handshaking async constructor protocol, use smarter routing ID assignment
ipc/glue/ProtocolUtils.h
ipc/ipdl/ipdl/lower.py
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -1,8 +1,11 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -40,65 +43,63 @@
 #include "chrome/common/ipc_message_utils.h"
 
 #include "mozilla/ipc/RPCChannel.h"
 
 namespace mozilla {
 namespace ipc {
 
 
-// Used to pass references to protocol actors across the wire.  An actor
-// has a parent-side "routing ID" and another routing ID on the child side.
+// Used to pass references to protocol actors across the wire.
+// Actors created on the parent-side have a positive ID, and actors
+// allocated on the child side have a negative ID.
 struct ActorHandle
 {
-    int mParentId;
-    int mChildId;
+    int mId;
 };
 
 
 template<class ListenerT>
 class /*NS_INTERFACE_CLASS*/ IProtocolManager
 {
 public:
     virtual int32 Register(ListenerT*) = 0;
+    virtual int32 RegisterID(ListenerT*, int32) = 0;
     virtual ListenerT* Lookup(int32) = 0;
     virtual void Unregister(int32) = 0;
 };
 
 } // namespace ipc
 } // namespace mozilla
 
 
 namespace IPC {
 
 template <>
 struct ParamTraits<mozilla::ipc::ActorHandle>
 {
-  typedef mozilla::ipc::ActorHandle paramType;
+    typedef mozilla::ipc::ActorHandle paramType;
 
-  static void Write(Message* aMsg, const paramType& aParam)
-  {
-    IPC::WriteParam(aMsg, aParam.mParentId);
-    IPC::WriteParam(aMsg, aParam.mChildId);
-  }
+    static void Write(Message* aMsg, const paramType& aParam)
+    {
+        IPC::WriteParam(aMsg, aParam.mId);
+    }
 
-  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
-  {
-    int parentId, childId;
-    if (IPC::ReadParam(aMsg, aIter, &parentId)
-        && ReadParam(aMsg, aIter, &childId)) {
-      aResult->mParentId = parentId;
-      aResult->mChildId = childId;
-      return true;
+    static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+    {
+        int id;
+        if (IPC::ReadParam(aMsg, aIter, &id)) {
+            aResult->mId = id;
+            return true;
+        }
+        return false;
     }
-    return false;
-  }
 
-  static void Log(const paramType& aParam, std::wstring* aLog)
-  {
-    aLog->append(StringPrintf(L"(%d,%d)", aParam.mParentId, aParam.mChildId));
-  }
+    static void Log(const paramType& aParam, std::wstring* aLog)
+    {
+        aLog->append(StringPrintf(L"(%d)", aParam.mId));
+    }
 };
 
 } // namespace IPC
 
 
 #endif  // mozilla_ipc_ProtocolUtils_h
--- 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