Bug 561817 part A: Entered/ExitedCall callbacks for toplevel actors upon RPC in-calls. r=bsmedberg

This commit is contained in:
Benjamin Smedberg 2010-04-29 11:49:00 -05:00
Родитель c1e8abd08d
Коммит 01cd6e47af
4 изменённых файлов: 112 добавлений и 9 удалений

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

@ -94,6 +94,16 @@ public:
NS_RUNTIMEABORT("default impl shouldn't be invoked"); NS_RUNTIMEABORT("default impl shouldn't be invoked");
} }
virtual void OnEnteredCall()
{
NS_RUNTIMEABORT("default impl shouldn't be invoked");
}
virtual void OnExitedCall()
{
NS_RUNTIMEABORT("default impl shouldn't be invoked");
}
virtual RacyRPCPolicy MediateRPCRace(const Message& parent, virtual RacyRPCPolicy MediateRPCRace(const Message& parent,
const Message& child) const Message& child)
{ {
@ -199,12 +209,32 @@ protected:
void ExitedCxxStack(); void ExitedCxxStack();
void EnteredCall()
{
Listener()->OnEnteredCall();
}
void ExitedCall()
{
Listener()->OnExitedCall();
}
enum Direction { IN_MESSAGE, OUT_MESSAGE }; enum Direction { IN_MESSAGE, OUT_MESSAGE };
struct RPCFrame { struct RPCFrame {
RPCFrame(Direction direction, const Message* msg) : RPCFrame(Direction direction, const Message* msg) :
mDirection(direction), mMsg(msg) mDirection(direction), mMsg(msg)
{ } { }
bool IsRPCIncall() const
{
return mMsg->is_rpc() && IN_MESSAGE == mDirection;
}
bool IsRPCOutcall() const
{
return mMsg->is_rpc() && OUT_MESSAGE == mDirection;
}
void Describe(int32* id, const char** dir, const char** sems, void Describe(int32* id, const char** dir, const char** sems,
const char** name) const const char** name) const
{ {
@ -230,11 +260,16 @@ protected:
mThat.EnteredCxxStack(); mThat.EnteredCxxStack();
mThat.mCxxStackFrames.push_back(RPCFrame(direction, msg)); mThat.mCxxStackFrames.push_back(RPCFrame(direction, msg));
mThat.mSawRPCOutMsg |= (direction == OUT_MESSAGE) && const RPCFrame& frame = mThat.mCxxStackFrames.back();
(msg->is_rpc());
if (frame.IsRPCIncall())
mThat.EnteredCall();
mThat.mSawRPCOutMsg |= frame.IsRPCOutcall();
} }
~CxxStackFrame() { ~CxxStackFrame() {
bool exitingCall = mThat.mCxxStackFrames.back().IsRPCIncall();
mThat.mCxxStackFrames.pop_back(); mThat.mCxxStackFrames.pop_back();
bool exitingStack = mThat.mCxxStackFrames.empty(); bool exitingStack = mThat.mCxxStackFrames.empty();
@ -244,6 +279,9 @@ protected:
return; return;
mThat.AssertWorkerThread(); mThat.AssertWorkerThread();
if (exitingCall)
mThat.ExitedCall();
if (exitingStack) if (exitingStack)
mThat.ExitedCxxStack(); mThat.ExitedCxxStack();
} }

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

@ -1408,6 +1408,14 @@ class Protocol(ipdl.ast.Protocol):
assert self.decl.type.isToplevel() assert self.decl.type.isToplevel()
return ExprVar('ExitedCxxStack') return ExprVar('ExitedCxxStack')
def enteredCallVar(self):
assert self.decl.type.isToplevel()
return ExprVar('EnteredCall')
def exitedCallVar(self):
assert self.decl.type.isToplevel()
return ExprVar('ExitedCall')
def onCxxStackVar(self): def onCxxStackVar(self):
assert self.decl.type.isToplevel() assert self.decl.type.isToplevel()
return ExprVar('IsOnCxxStack') return ExprVar('IsOnCxxStack')
@ -2709,13 +2717,19 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ret=Type.BOOL, virtual=1)) ret=Type.BOOL, virtual=1))
shouldcontinue.addstmt(StmtReturn(ExprLiteral.TRUE)) shouldcontinue.addstmt(StmtReturn(ExprLiteral.TRUE))
# void EnteredCxxStack(); default to no-op # void Entered*()/Exited*(); default to no-op
entered = MethodDefn( entered = MethodDefn(
MethodDecl(p.enteredCxxStackVar().name, virtual=1)) MethodDecl(p.enteredCxxStackVar().name, virtual=1))
exited = MethodDefn( exited = MethodDefn(
MethodDecl(p.exitedCxxStackVar().name, virtual=1)) MethodDecl(p.exitedCxxStackVar().name, virtual=1))
enteredcall = MethodDefn(
MethodDecl(p.enteredCallVar().name, virtual=1))
exitedcall = MethodDefn(
MethodDecl(p.exitedCallVar().name, virtual=1))
self.cls.addstmts([ shouldcontinue, entered, exited, self.cls.addstmts([ shouldcontinue,
entered, exited,
enteredcall, exitedcall,
Whitespace.NL ]) Whitespace.NL ])
self.cls.addstmts(( self.cls.addstmts((
@ -2950,13 +2964,23 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
onexited = MethodDefn(MethodDecl('OnExitedCxxStack')) onexited = MethodDefn(MethodDecl('OnExitedCxxStack'))
onexited.addstmt(StmtReturn(ExprCall(p.exitedCxxStackVar()))) onexited.addstmt(StmtReturn(ExprCall(p.exitedCxxStackVar())))
# OnEnteredCxxStack()
onenteredcall = MethodDefn(MethodDecl('OnEnteredCall'))
onenteredcall.addstmt(StmtReturn(ExprCall(p.enteredCallVar())))
# OnExitedCxxStack()
onexitedcall = MethodDefn(MethodDecl('OnExitedCall'))
onexitedcall.addstmt(StmtReturn(ExprCall(p.exitedCallVar())))
# bool IsOnCxxStack() # bool IsOnCxxStack()
onstack = MethodDefn( onstack = MethodDefn(
MethodDecl(p.onCxxStackVar().name, ret=Type.BOOL, const=1)) MethodDecl(p.onCxxStackVar().name, ret=Type.BOOL, const=1))
onstack.addstmt(StmtReturn(ExprCall( onstack.addstmt(StmtReturn(ExprCall(
ExprSelect(p.channelVar(), '.', p.onCxxStackVar().name)))) ExprSelect(p.channelVar(), '.', p.onCxxStackVar().name))))
self.cls.addstmts([ onentered, onexited, onstack, Whitespace.NL ]) self.cls.addstmts([ onentered, onexited,
onenteredcall, onexitedcall,
onstack, Whitespace.NL ])
# OnChannelClose() # OnChannelClose()
onclose = MethodDefn(MethodDecl('OnChannelClose')) onclose = MethodDefn(MethodDecl('OnChannelClose'))

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

@ -10,7 +10,8 @@ namespace _ipdltest {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// parent // parent
TestStackHooksParent::TestStackHooksParent() : mOnStack(false) TestStackHooksParent::TestStackHooksParent() :
mOnStack(false), mIncallDepth(0)
{ {
MOZ_COUNT_CTOR(TestStackHooksParent); MOZ_COUNT_CTOR(TestStackHooksParent);
} }
@ -40,6 +41,9 @@ TestStackHooksParent::AnswerStackFrame()
if (!mOnStack) if (!mOnStack)
fail("not on C++ stack?!"); fail("not on C++ stack?!");
if (1 != mIncallDepth)
fail("missed EnteredCall or ExitedCall hook");
return true; return true;
} }
@ -49,7 +53,8 @@ TestStackHooksParent::AnswerStackFrame()
TestStackHooksChild::TestStackHooksChild() : TestStackHooksChild::TestStackHooksChild() :
mOnStack(false), mOnStack(false),
mEntered(0), mEntered(0),
mExited(0) mExited(0),
mIncallDepth(0)
{ {
MOZ_COUNT_CTOR(TestStackHooksChild); MOZ_COUNT_CTOR(TestStackHooksChild);
} }
@ -71,6 +76,9 @@ TestStackHooksChild::RecvStart()
if (!mOnStack) if (!mOnStack)
fail("missed stack notification"); fail("missed stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
// kick off tests from a runnable so that we can start with // kick off tests from a runnable so that we can start with
// RPCChannel code on the C++ stack // RPCChannel code on the C++ stack
MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::current()->PostTask(FROM_HERE,
@ -85,12 +93,15 @@ TestStackHooksChild::AnswerStackFrame()
if (!mOnStack) if (!mOnStack)
fail("missed stack notification"); fail("missed stack notification");
if (1 != mIncallDepth)
fail("missed EnteredCall or ExitedCall hook");
// FIXME use IPDL state instead // FIXME use IPDL state instead
if (4 == mEntered) { if (4 == mEntered) { // test 4
if (!SendAsync()) if (!SendAsync())
fail("sending Async()"); fail("sending Async()");
} }
else if (5 == mEntered) { else if (5 == mEntered) { // test 5
if (!SendSync()) if (!SendSync())
fail("sending Sync()"); fail("sending Sync()");
} }
@ -112,11 +123,15 @@ TestStackHooksChild::RunTests()
fail("missed stack notification"); fail("missed stack notification");
if (mOnStack) if (mOnStack)
fail("spurious stack notification"); fail("spurious stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
if (!SendAsync()) if (!SendAsync())
fail("sending Async()"); fail("sending Async()");
if (mOnStack) if (mOnStack)
fail("spurious stack notification"); fail("spurious stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
if (2 != mEntered) if (2 != mEntered)
fail("missed stack notification"); fail("missed stack notification");
@ -124,6 +139,8 @@ TestStackHooksChild::RunTests()
fail("sending Sync()"); fail("sending Sync()");
if (mOnStack) if (mOnStack)
fail("spurious stack notification"); fail("spurious stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
if (3 != mEntered) if (3 != mEntered)
fail("missed stack notification"); fail("missed stack notification");
@ -131,6 +148,8 @@ TestStackHooksChild::RunTests()
fail("calling RPC()"); fail("calling RPC()");
if (mOnStack) if (mOnStack)
fail("spurious stack notification"); fail("spurious stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
if (4 != mEntered) if (4 != mEntered)
fail("missed stack notification"); fail("missed stack notification");
@ -138,6 +157,8 @@ TestStackHooksChild::RunTests()
fail("calling StackFrame()"); fail("calling StackFrame()");
if (mOnStack) if (mOnStack)
fail("spurious stack notification"); fail("spurious stack notification");
if (0 != mIncallDepth)
fail("EnteredCall/ExitedCall malfunction");
if (5 != mEntered) if (5 != mEntered)
fail("missed stack notification"); fail("missed stack notification");

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

@ -62,8 +62,18 @@ protected:
mOnStack = false; mOnStack = false;
} }
NS_OVERRIDE
virtual void EnteredCall() {
++mIncallDepth;
}
NS_OVERRIDE
virtual void ExitedCall() {
--mIncallDepth;
}
private: private:
bool mOnStack; bool mOnStack;
int mIncallDepth;
}; };
@ -109,10 +119,20 @@ protected:
mOnStack = false; mOnStack = false;
} }
NS_OVERRIDE
virtual void EnteredCall() {
++mIncallDepth;
}
NS_OVERRIDE
virtual void ExitedCall() {
--mIncallDepth;
}
private: private:
bool mOnStack; bool mOnStack;
int mEntered; int mEntered;
int mExited; int mExited;
int mIncallDepth;
}; };