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");
}
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,
const Message& child)
{
@ -199,12 +209,32 @@ protected:
void ExitedCxxStack();
void EnteredCall()
{
Listener()->OnEnteredCall();
}
void ExitedCall()
{
Listener()->OnExitedCall();
}
enum Direction { IN_MESSAGE, OUT_MESSAGE };
struct RPCFrame {
RPCFrame(Direction direction, const Message* 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,
const char** name) const
{
@ -230,11 +260,16 @@ protected:
mThat.EnteredCxxStack();
mThat.mCxxStackFrames.push_back(RPCFrame(direction, msg));
mThat.mSawRPCOutMsg |= (direction == OUT_MESSAGE) &&
(msg->is_rpc());
const RPCFrame& frame = mThat.mCxxStackFrames.back();
if (frame.IsRPCIncall())
mThat.EnteredCall();
mThat.mSawRPCOutMsg |= frame.IsRPCOutcall();
}
~CxxStackFrame() {
bool exitingCall = mThat.mCxxStackFrames.back().IsRPCIncall();
mThat.mCxxStackFrames.pop_back();
bool exitingStack = mThat.mCxxStackFrames.empty();
@ -244,6 +279,9 @@ protected:
return;
mThat.AssertWorkerThread();
if (exitingCall)
mThat.ExitedCall();
if (exitingStack)
mThat.ExitedCxxStack();
}

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

@ -1408,6 +1408,14 @@ class Protocol(ipdl.ast.Protocol):
assert self.decl.type.isToplevel()
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):
assert self.decl.type.isToplevel()
return ExprVar('IsOnCxxStack')
@ -2709,13 +2717,19 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ret=Type.BOOL, virtual=1))
shouldcontinue.addstmt(StmtReturn(ExprLiteral.TRUE))
# void EnteredCxxStack(); default to no-op
# void Entered*()/Exited*(); default to no-op
entered = MethodDefn(
MethodDecl(p.enteredCxxStackVar().name, virtual=1))
exited = MethodDefn(
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 ])
self.cls.addstmts((
@ -2950,13 +2964,23 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
onexited = MethodDefn(MethodDecl('OnExitedCxxStack'))
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()
onstack = MethodDefn(
MethodDecl(p.onCxxStackVar().name, ret=Type.BOOL, const=1))
onstack.addstmt(StmtReturn(ExprCall(
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()
onclose = MethodDefn(MethodDecl('OnChannelClose'))

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

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

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

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