Bug 939182 - Clean up message loop code, r=bsmedberg.

--HG--
extra : transplant_source : -v1T%0A%B7%FC%B3q%CE//%D7%EB%3C%2C1%B4%F8%F1
This commit is contained in:
Ben Turner 2013-10-23 01:28:24 -07:00
parent 9de016148a
commit 436bc9d8e6
2 changed files with 116 additions and 84 deletions

View File

@ -4,16 +4,23 @@
#include "MessagePump.h"
#include "nsIRunnable.h"
#include "nsIThread.h"
#include "nsITimer.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/scoped_nsautorelease_pool.h"
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "nsComponentManagerUtils.h"
#include "nsDebug.h"
#include "nsServiceManagerUtils.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
#include "prthread.h"
#include "base/logging.h"
#include "base/scoped_nsautorelease_pool.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
@ -22,42 +29,37 @@
#include "ipc/Nuwa.h"
#endif
using mozilla::ipc::DoWorkRunnable;
using mozilla::ipc::MessagePump;
using mozilla::ipc::MessagePumpForChildProcess;
using base::TimeTicks;
using namespace mozilla::ipc;
NS_IMPL_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
static mozilla::DebugOnly<MessagePump::Delegate*> gFirstDelegate;
NS_IMETHODIMP
DoWorkRunnable::Run()
namespace mozilla {
namespace ipc {
class DoWorkRunnable MOZ_FINAL : public nsIRunnable,
public nsITimerCallback
{
MessageLoop* loop = MessageLoop::current();
NS_ASSERTION(loop, "Shouldn't be null!");
if (loop) {
bool nestableTasksAllowed = loop->NestableTasksAllowed();
// MessageLoop::RunTask() disallows nesting, but our Frankenventloop
// will always dispatch DoWork() below from what looks to
// MessageLoop like a nested context. So we unconditionally allow
// nesting here.
loop->SetNestableTasksAllowed(true);
loop->DoWork();
loop->SetNestableTasksAllowed(nestableTasksAllowed);
public:
DoWorkRunnable(MessagePump* aPump)
: mPump(aPump)
{
MOZ_ASSERT(aPump);
}
return NS_OK;
}
NS_IMETHODIMP
DoWorkRunnable::Notify(nsITimer* aTimer)
{
MessageLoop* loop = MessageLoop::current();
NS_ASSERTION(loop, "Shouldn't be null!");
if (loop) {
mPump->DoDelayedWork(loop);
}
return NS_OK;
}
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSITIMERCALLBACK
private:
~DoWorkRunnable()
{ }
MessagePump* mPump;
};
} /* namespace ipc */
} /* namespace mozilla */
MessagePump::MessagePump()
: mThread(nullptr)
@ -65,17 +67,21 @@ MessagePump::MessagePump()
mDoWorkEvent = new DoWorkRunnable(this);
}
MessagePump::~MessagePump()
{
}
void
MessagePump::Run(MessagePump::Delegate* aDelegate)
{
NS_ASSERTION(keep_running_, "Quit must have been called outside of Run!");
NS_ASSERTION(NS_IsMainThread(), "Called Run on the wrong thread!");
MOZ_ASSERT(keep_running_);
MOZ_ASSERT(NS_IsMainThread());
mThread = NS_GetCurrentThread();
NS_ASSERTION(mThread, "This should never be null!");
MOZ_ASSERT(mThread);
mDelayedWorkTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
NS_ASSERTION(mDelayedWorkTimer, "Failed to create timer!");
MOZ_ASSERT(mDelayedWorkTimer);
base::ScopedNSAutoreleasePool autoReleasePool;
@ -199,34 +205,56 @@ MessagePump::DoDelayedWork(base::MessagePump::Delegate* aDelegate)
}
}
#ifdef DEBUG
namespace {
MessagePump::Delegate* gFirstDelegate = nullptr;
NS_IMPL_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
NS_IMETHODIMP
DoWorkRunnable::Run()
{
MessageLoop* loop = MessageLoop::current();
MOZ_ASSERT(loop);
bool nestableTasksAllowed = loop->NestableTasksAllowed();
// MessageLoop::RunTask() disallows nesting, but our Frankenventloop will
// always dispatch DoWork() below from what looks to MessageLoop like a nested
// context. So we unconditionally allow nesting here.
loop->SetNestableTasksAllowed(true);
loop->DoWork();
loop->SetNestableTasksAllowed(nestableTasksAllowed);
return NS_OK;
}
NS_IMETHODIMP
DoWorkRunnable::Notify(nsITimer* aTimer)
{
MessageLoop* loop = MessageLoop::current();
MOZ_ASSERT(loop);
mPump->DoDelayedWork(loop);
return NS_OK;
}
#endif
void
MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
MessagePumpForChildProcess::Run(base::MessagePump::Delegate* aDelegate)
{
if (mFirstRun) {
#ifdef DEBUG
NS_ASSERTION(aDelegate && gFirstDelegate == nullptr, "Huh?!");
MOZ_ASSERT(aDelegate && !gFirstDelegate);
gFirstDelegate = aDelegate;
#endif
mFirstRun = false;
if (NS_FAILED(XRE_RunAppShell())) {
NS_WARNING("Failed to run app shell?!");
}
#ifdef DEBUG
NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
MOZ_ASSERT(aDelegate && aDelegate == gFirstDelegate);
gFirstDelegate = nullptr;
#endif
return;
}
#ifdef DEBUG
NS_ASSERTION(aDelegate && aDelegate == gFirstDelegate, "Huh?!");
#endif
MOZ_ASSERT(aDelegate && aDelegate == gFirstDelegate);
// We can get to this point in startup with Tasks in our loop's
// incoming_queue_ or pending_queue_, but without a matching
@ -245,7 +273,6 @@ MessagePumpForChildProcess::Run(MessagePump::Delegate* aDelegate)
loop->SetNestableTasksAllowed(nestableTasksAllowed);
// Really run.
mozilla::ipc::MessagePump::Run(aDelegate);
}

View File

@ -5,69 +5,74 @@
#ifndef __IPC_GLUE_MESSAGEPUMP_H__
#define __IPC_GLUE_MESSAGEPUMP_H__
#include "base/basictypes.h"
#include "base/message_pump_default.h"
#include "base/time.h"
#include "mozilla/Attributes.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIRunnable.h"
#include "nsIThread.h"
#include "nsITimer.h"
#include "mozilla/Attributes.h"
class nsIThread;
class nsITimer;
namespace mozilla {
namespace ipc {
class MessagePump;
class DoWorkRunnable MOZ_FINAL : public nsIRunnable,
public nsITimerCallback
{
public:
DoWorkRunnable(MessagePump* aPump)
: mPump(aPump) { }
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSITIMERCALLBACK
private:
MessagePump* mPump;
};
class DoWorkRunnable;
class MessagePump : public base::MessagePumpDefault
{
friend class DoWorkRunnable;
public:
MessagePump();
virtual void Run(base::MessagePump::Delegate* aDelegate);
virtual void ScheduleWork();
virtual void ScheduleWorkForNestedLoop();
virtual void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time);
// From base::MessagePump.
virtual void
Run(base::MessagePump::Delegate* aDelegate) MOZ_OVERRIDE;
void DoDelayedWork(base::MessagePump::Delegate* aDelegate);
// From base::MessagePump.
virtual void
ScheduleWork() MOZ_OVERRIDE;
// From base::MessagePump.
virtual void
ScheduleWorkForNestedLoop() MOZ_OVERRIDE;
// From base::MessagePump.
virtual void
ScheduleDelayedWork(const base::TimeTicks& aDelayedWorkTime) MOZ_OVERRIDE;
protected:
virtual ~MessagePump();
private:
nsRefPtr<DoWorkRunnable> mDoWorkEvent;
nsCOMPtr<nsITimer> mDelayedWorkTimer;
// Only called by DoWorkRunnable.
void DoDelayedWork(base::MessagePump::Delegate* aDelegate);
// Weak!
protected:
// mDelayedWorkTimer and mThread are set in Run() by this class or its
// subclasses.
nsCOMPtr<nsITimer> mDelayedWorkTimer;
nsIThread* mThread;
private:
// Only accessed by this class.
nsRefPtr<DoWorkRunnable> mDoWorkEvent;
};
class MessagePumpForChildProcess : public MessagePump
class MessagePumpForChildProcess MOZ_FINAL: public MessagePump
{
public:
MessagePumpForChildProcess()
: mFirstRun(true)
{ }
virtual void Run(base::MessagePump::Delegate* aDelegate);
virtual void Run(base::MessagePump::Delegate* aDelegate) MOZ_OVERRIDE;
private:
~MessagePumpForChildProcess()
{ }
bool mFirstRun;
};