Bug 1337537 - Move Dispatcher.{cpp,h} to xpcom/threads (r=froydnj)

MozReview-Commit-ID: AYyKynUv4bX
This commit is contained in:
Bill McCloskey 2017-01-30 16:13:18 -08:00
parent 82ad45b35d
commit bea9c4205c
14 changed files with 193 additions and 143 deletions

View File

@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_Dispatcher_h
#define mozilla_dom_Dispatcher_h
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/TaskCategory.h"
#include "nsISupports.h"
class nsIEventTarget;
class nsIRunnable;
// This file defines basic functionality for dispatching runnables to various
// groups: either the SystemGroup or a DocGroup or TabGroup. Ideally all
// runnables destined for the main thread should be dispatched to a group
// instead so that we know what kind of web content they'll be
// touching. Runnables sent to the SystemGroup never touch web
// content. Runnables sent to a DocGroup can only touch documents belonging to
// that DocGroup. Runnables sent to a TabGroup can touch any document in any of
// the tabs belonging to the TabGroup.
namespace mozilla {
class AbstractThread;
namespace dom {
class TabGroup;
// This trait should be attached to classes like nsIGlobalObject and nsIDocument
// that have a DocGroup or TabGroup attached to them. The methods here should
// delegate to the DocGroup or TabGroup. We can't use the Dispatcher class
// directly because it inherits from nsISupports.
class DispatcherTrait {
public:
// This method may or may not be safe off of the main thread. For nsIDocument
// it is safe. For nsIGlobalWindow it is not safe.
virtual nsresult Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable);
// This method may or may not be safe off of the main thread. For nsIDocument
// it is safe. For nsIGlobalWindow it is not safe. The nsIEventTarget can
// always be used off the main thread.
virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const;
// Must be called on the main thread. The AbstractThread can always be used
// off the main thread.
virtual AbstractThread* AbstractMainThreadFor(TaskCategory aCategory);
};
// Base class for DocGroup and TabGroup.
class Dispatcher : public nsISupports {
public:
// This method is always safe to call off the main thread.
virtual nsresult Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) = 0;
// This method is always safe to call off the main thread. The nsIEventTarget
// can always be used off the main thread.
virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const = 0;
// Must be called on the main thread. The AbstractThread can always be used
// off the main thread.
virtual AbstractThread* AbstractMainThreadFor(TaskCategory aCategory) = 0;
// This method performs a safe cast. It returns null if |this| is not of the
// requested type.
virtual TabGroup* AsTabGroup() { return nullptr; }
protected:
virtual already_AddRefed<nsIEventTarget>
CreateEventTargetFor(TaskCategory aCategory);
static Dispatcher* FromEventTarget(nsIEventTarget* aEventTarget);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_Dispatcher_h

View File

@ -0,0 +1,45 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/DispatcherTrait.h"
#include "mozilla/AbstractThread.h"
#include "nsINamed.h"
using namespace mozilla;
using namespace mozilla::dom;
nsresult
DispatcherTrait::Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable)
{
nsCOMPtr<nsIRunnable> runnable(aRunnable);
if (aName) {
if (nsCOMPtr<nsINamed> named = do_QueryInterface(runnable)) {
named->SetName(aName);
}
}
if (NS_IsMainThread()) {
return NS_DispatchToCurrentThread(runnable.forget());
} else {
return NS_DispatchToMainThread(runnable.forget());
}
}
nsIEventTarget*
DispatcherTrait::EventTargetFor(TaskCategory aCategory) const
{
nsCOMPtr<nsIEventTarget> main = do_GetMainThread();
return main;
}
AbstractThread*
DispatcherTrait::AbstractMainThreadFor(TaskCategory aCategory)
{
// Return non DocGroup version by default.
return AbstractThread::MainThread();
}

View File

@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DispatcherTrait_h
#define mozilla_dom_DispatcherTrait_h
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/TaskCategory.h"
class nsIEventTarget;
class nsIRunnable;
namespace mozilla {
class AbstractThread;
namespace dom {
class TabGroup;
// This trait should be attached to classes like nsIGlobalObject and nsIDocument
// that have a DocGroup or TabGroup attached to them. The methods here should
// delegate to the DocGroup or TabGroup. We can't use the Dispatcher class
// directly because it inherits from nsISupports.
class DispatcherTrait {
public:
// This method may or may not be safe off of the main thread. For nsIDocument
// it is safe. For nsIGlobalWindow it is not safe.
virtual nsresult Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable);
// This method may or may not be safe off of the main thread. For nsIDocument
// it is safe. For nsIGlobalWindow it is not safe. The nsIEventTarget can
// always be used off the main thread.
virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const;
// Must be called on the main thread. The AbstractThread can always be used
// off the main thread.
virtual AbstractThread* AbstractMainThreadFor(TaskCategory aCategory);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DispatcherTrait_h

View File

@ -49,8 +49,6 @@ DocGroup::~DocGroup()
mTabGroup->mDocGroups.RemoveEntry(mKey);
}
NS_IMPL_ISUPPORTS(DocGroup, nsISupports)
nsresult
DocGroup::Dispatch(const char* aName,
TaskCategory aCategory,
@ -66,7 +64,7 @@ DocGroup::EventTargetFor(TaskCategory aCategory) const
}
AbstractThread*
DocGroup::AbstractMainThreadFor(TaskCategory aCategory)
DocGroup::AbstractMainThreadForImpl(TaskCategory aCategory)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
return mTabGroup->AbstractMainThreadFor(aCategory);

View File

@ -7,13 +7,12 @@
#ifndef DocGroup_h
#define DocGroup_h
#include "nsISupports.h"
#include "nsISupportsImpl.h"
#include "nsIPrincipal.h"
#include "nsTHashtable.h"
#include "nsString.h"
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/Dispatcher.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
@ -43,7 +42,7 @@ public:
typedef nsTArray<nsIDocument*>::iterator Iterator;
friend class TabGroup;
NS_DECL_THREADSAFE_ISUPPORTS
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DocGroup, override)
// Returns NS_ERROR_FAILURE and sets |aString| to an empty string if the TLD
// service isn't available. Returns NS_OK on success, but may still set
@ -77,10 +76,10 @@ public:
virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const override;
virtual AbstractThread*
AbstractMainThreadFor(TaskCategory aCategory) override;
private:
virtual AbstractThread*
AbstractMainThreadForImpl(TaskCategory aCategory) override;
DocGroup(TabGroup* aTabGroup, const nsACString& aKey);
~DocGroup();

View File

@ -243,8 +243,6 @@ TabGroup::GetTopLevelWindows()
return array;
}
NS_IMPL_ISUPPORTS(TabGroup, nsISupports)
TabGroup::HashEntry::HashEntry(const nsACString* aKey)
: nsCStringHashKey(aKey), mDocGroup(nullptr)
{}
@ -286,7 +284,7 @@ TabGroup::EventTargetFor(TaskCategory aCategory) const
}
AbstractThread*
TabGroup::AbstractMainThreadFor(TaskCategory aCategory)
TabGroup::AbstractMainThreadForImpl(TaskCategory aCategory)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCategory != TaskCategory::Count);

View File

@ -7,14 +7,13 @@
#ifndef TabGroup_h
#define TabGroup_h
#include "nsISupports.h"
#include "nsISupportsImpl.h"
#include "nsIPrincipal.h"
#include "nsTHashtable.h"
#include "nsString.h"
#include "mozilla/Atomics.h"
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/Dispatcher.h"
#include "mozilla/RefPtr.h"
namespace mozilla {
@ -57,7 +56,7 @@ public:
friend class DocGroup;
NS_DECL_THREADSAFE_ISUPPORTS
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TabGroup, override)
static TabGroup*
GetChromeTabGroup();
@ -122,10 +121,10 @@ public:
TabGroup* AsTabGroup() override { return this; }
virtual AbstractThread*
AbstractMainThreadFor(TaskCategory aCategory) override;
private:
virtual AbstractThread*
AbstractMainThreadForImpl(TaskCategory aCategory) override;
void EnsureThrottledEventQueues();
~TabGroup();

View File

@ -154,7 +154,7 @@ EXPORTS.mozilla.dom += [
'Comment.h',
'CustomElementRegistry.h',
'DirectionalityUtils.h',
'Dispatcher.h',
'DispatcherTrait.h',
'DocGroup.h',
'DocumentFragment.h',
'DocumentType.h',
@ -226,7 +226,7 @@ UNIFIED_SOURCES += [
'Crypto.cpp',
'CustomElementRegistry.cpp',
'DirectionalityUtils.cpp',
'Dispatcher.cpp',
'DispatcherTrait.cpp',
'DocGroup.cpp',
'DocumentFragment.cpp',
'DocumentType.cpp',

View File

@ -32,7 +32,7 @@
#include "nsClassHashtable.h"
#include "prclist.h"
#include "mozilla/CORSMode.h"
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/dom/DispatcherTrait.h"
#include "mozilla/LinkedList.h"
#include "mozilla/StyleBackendType.h"
#include "mozilla/StyleSheet.h"

View File

@ -7,7 +7,7 @@
#ifndef nsIGlobalObject_h__
#define nsIGlobalObject_h__
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/dom/DispatcherTrait.h"
#include "nsISupports.h"
#include "nsTArray.h"
#include "js/TypeDecls.h"

View File

@ -12,8 +12,8 @@
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/TaskCategory.h"
#include "js/TypeDecls.h"
#include "nsRefPtrHashtable.h"
@ -29,6 +29,7 @@ class nsICSSDeclaration;
class nsIDocShell;
class nsIDocShellLoadInfo;
class nsIDocument;
class nsIEventTarget;
class nsIIdleObserver;
class nsIPrincipal;
class nsIScriptTimeoutHandler;

View File

@ -4,7 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/Dispatcher.h"
#include "mozilla/Dispatcher.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Move.h"
@ -13,38 +13,6 @@
using namespace mozilla;
nsresult
DispatcherTrait::Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable)
{
nsCOMPtr<nsIRunnable> runnable(aRunnable);
if (aName) {
if (nsCOMPtr<nsINamed> named = do_QueryInterface(runnable)) {
named->SetName(aName);
}
}
if (NS_IsMainThread()) {
return NS_DispatchToCurrentThread(runnable.forget());
} else {
return NS_DispatchToMainThread(runnable.forget());
}
}
nsIEventTarget*
DispatcherTrait::EventTargetFor(TaskCategory aCategory) const
{
nsCOMPtr<nsIEventTarget> main = do_GetMainThread();
return main;
}
AbstractThread*
DispatcherTrait::AbstractMainThreadFor(TaskCategory aCategory)
{
// Return non DocGroup version by default.
return AbstractThread::MainThread();
}
namespace {
#define NS_DISPATCHEREVENTTARGET_IID \
@ -53,13 +21,13 @@ namespace {
class DispatcherEventTarget final : public nsIEventTarget
{
RefPtr<dom::Dispatcher> mDispatcher;
RefPtr<Dispatcher> mDispatcher;
TaskCategory mCategory;
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_DISPATCHEREVENTTARGET_IID)
DispatcherEventTarget(dom::Dispatcher* aDispatcher, TaskCategory aCategory)
DispatcherEventTarget(Dispatcher* aDispatcher, TaskCategory aCategory)
: mDispatcher(aDispatcher)
, mCategory(aCategory)
{}
@ -67,10 +35,10 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET
dom::Dispatcher* Dispatcher() const { return mDispatcher; }
Dispatcher* Dispatcher() const { return mDispatcher; }
private:
virtual ~DispatcherEventTarget() {}
~DispatcherEventTarget() {}
};
NS_DEFINE_STATIC_IID_ACCESSOR(DispatcherEventTarget, NS_DISPATCHEREVENTTARGET_IID)
@ -107,6 +75,13 @@ DispatcherEventTarget::IsOnCurrentThread(bool* aIsOnCurrentThread)
return NS_OK;
}
AbstractThread*
Dispatcher::AbstractMainThreadFor(TaskCategory aCategory)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
return AbstractMainThreadForImpl(aCategory);
}
already_AddRefed<nsIEventTarget>
Dispatcher::CreateEventTargetFor(TaskCategory aCategory)
{

View File

@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_Dispatcher_h
#define mozilla_Dispatcher_h
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/TaskCategory.h"
#include "nsISupportsImpl.h"
class nsIEventTarget;
class nsIRunnable;
namespace mozilla {
class AbstractThread;
namespace dom {
class TabGroup;
}
// The "main thread" in Gecko will soon be a set of cooperatively scheduled
// "fibers". Global state in Gecko will be partitioned into a series of "groups"
// (with roughly one group per tab). Runnables will be annotated with the set of
// groups that they touch. Two runnables may run concurrently on different
// fibers as long as they touch different groups.
//
// A Dispatcher is an abstract class to represent a "group". Essentially the
// only functionality offered by a Dispatcher is the ability to dispatch
// runnables to the group. TabGroup, DocGroup, and SystemGroup are the concrete
// implementations of Dispatcher.
class Dispatcher {
public:
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
// Implementations of this method must be safe to call off the main thread.
virtual nsresult Dispatch(const char* aName,
TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) = 0;
// Implementations of this method must be safe to call off the main thread.
// The returned nsIEventTarget must also be usable from any thread.
virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const = 0;
// Must always be called on the main thread. The returned AbstractThread can
// always be used off the main thread.
AbstractThread* AbstractMainThreadFor(TaskCategory aCategory);
// This method performs a safe cast. It returns null if |this| is not of the
// requested type.
virtual dom::TabGroup* AsTabGroup() { return nullptr; }
protected:
// Implementations are guaranteed that this method is called on the main
// thread.
virtual AbstractThread* AbstractMainThreadForImpl(TaskCategory aCategory) = 0;
// Helper method to create an event target specific to a particular TaskCategory.
virtual already_AddRefed<nsIEventTarget>
CreateEventTargetFor(TaskCategory aCategory);
// Given an event target returned by |dispatcher->CreateEventTargetFor|, this
// function returns |dispatcher|.
static Dispatcher* FromEventTarget(nsIEventTarget* aEventTarget);
};
} // namespace mozilla
#endif // mozilla_dom_Dispatcher_h

View File

@ -39,6 +39,7 @@ EXPORTS.mozilla += [
'BlockingResourceBase.h',
'CondVar.h',
'DeadlockDetector.h',
'Dispatcher.h',
'HangAnnotations.h',
'HangMonitor.h',
'LazyIdleThread.h',
@ -62,6 +63,7 @@ UNIFIED_SOURCES += [
'AbstractThread.cpp',
'BackgroundHangMonitor.cpp',
'BlockingResourceBase.cpp',
'Dispatcher.cpp',
'HangAnnotations.cpp',
'HangMonitor.cpp',
'LazyIdleThread.cpp',