зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1366089 Make EventTargetFor() support worker threads. r=baku
This commit is contained in:
Родитель
f660d24cb3
Коммит
227c73cd89
|
@ -2067,7 +2067,7 @@ public:
|
|||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
// Note, Disable() can be called more than once safely.
|
||||
mWorkerPrivate = nullptr;
|
||||
mNestedEventTarget.swap(nestedEventTarget);
|
||||
}
|
||||
|
@ -2981,22 +2981,34 @@ WorkerPrivateParent<Derived>::GetEventTarget()
|
|||
|
||||
nsCOMPtr<nsISerialEventTarget> target;
|
||||
|
||||
bool needAutoDisable = false;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (!mEventTarget &&
|
||||
ParentStatus() <= Running &&
|
||||
self->mStatus <= Running) {
|
||||
if (!mEventTarget) {
|
||||
mEventTarget = new EventTarget(self);
|
||||
|
||||
// If the worker is already shutting down then we want to
|
||||
// immediately disable the event target. This will cause
|
||||
// the Dispatch() method to fail, but the event target
|
||||
// will still exist.
|
||||
if (self->mStatus > Running) {
|
||||
needAutoDisable = true;
|
||||
}
|
||||
}
|
||||
|
||||
target = mEventTarget;
|
||||
}
|
||||
|
||||
NS_WARNING_ASSERTION(
|
||||
target,
|
||||
"Requested event target for a worker that is already shutting down!");
|
||||
// Make sure to call Disable() outside of the mutex since it
|
||||
// also internally locks a mutex.
|
||||
if (needAutoDisable) {
|
||||
mEventTarget->Disable();
|
||||
}
|
||||
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(target);
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
|
@ -6134,7 +6146,6 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
MutexAutoLock lock(mMutex);
|
||||
|
||||
if (mStatus >= aStatus) {
|
||||
MOZ_ASSERT(!mEventTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6147,18 +6158,16 @@ WorkerPrivate::NotifyInternal(JSContext* aCx, Status aStatus)
|
|||
Close();
|
||||
}
|
||||
|
||||
mEventTarget.swap(eventTarget);
|
||||
eventTarget = mEventTarget;
|
||||
}
|
||||
|
||||
// Now that mStatus > Running, no-one can create a new WorkerEventTarget or
|
||||
// WorkerCrossThreadDispatcher if we don't already have one.
|
||||
// Disable the event target, if it exists.
|
||||
if (eventTarget) {
|
||||
// Since we'll no longer process events, make sure we no longer allow anyone
|
||||
// to post them. We have to do this without mMutex held, since our mutex
|
||||
// must be acquired *after* the WorkerEventTarget's mutex when they're both
|
||||
// held.
|
||||
eventTarget->Disable();
|
||||
eventTarget = nullptr;
|
||||
}
|
||||
|
||||
if (mCrossThreadDispatcher) {
|
||||
|
|
|
@ -72,10 +72,14 @@ using mozilla::dom::cache::CacheStorage;
|
|||
using mozilla::ipc::PrincipalInfo;
|
||||
|
||||
WorkerGlobalScope::WorkerGlobalScope(WorkerPrivate* aWorkerPrivate)
|
||||
: mWindowInteractionsAllowed(0)
|
||||
: mSerialEventTarget(aWorkerPrivate->GetEventTarget())
|
||||
, mWindowInteractionsAllowed(0)
|
||||
, mWorkerPrivate(aWorkerPrivate)
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// We should always have an event target when the global is created.
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
|
||||
}
|
||||
|
||||
WorkerGlobalScope::~WorkerGlobalScope()
|
||||
|
@ -489,6 +493,26 @@ WorkerGlobalScope::CreateImageBitmap(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
WorkerGlobalScope::Dispatch(const char* aName, TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
return EventTargetFor(aCategory)->Dispatch(Move(aRunnable),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsISerialEventTarget*
|
||||
WorkerGlobalScope::EventTargetFor(TaskCategory aCategory) const
|
||||
{
|
||||
return mSerialEventTarget;
|
||||
}
|
||||
|
||||
AbstractThread*
|
||||
WorkerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
|
||||
{
|
||||
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
|
||||
}
|
||||
|
||||
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
|
||||
const nsString& aName)
|
||||
: WorkerGlobalScope(aWorkerPrivate)
|
||||
|
@ -836,8 +860,12 @@ ServiceWorkerGlobalScope::OpenWindowEnabled(JSContext* aCx, JSObject* aObj)
|
|||
WorkerDebuggerGlobalScope::WorkerDebuggerGlobalScope(
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
: mWorkerPrivate(aWorkerPrivate)
|
||||
, mSerialEventTarget(aWorkerPrivate->GetEventTarget())
|
||||
{
|
||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
// We should always have an event target when the global is created.
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSerialEventTarget);
|
||||
}
|
||||
|
||||
WorkerDebuggerGlobalScope::~WorkerDebuggerGlobalScope()
|
||||
|
@ -1051,6 +1079,26 @@ WorkerDebuggerGlobalScope::Dump(JSContext* aCx,
|
|||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
WorkerDebuggerGlobalScope::Dispatch(const char* aName, TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
return EventTargetFor(aCategory)->Dispatch(Move(aRunnable),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsISerialEventTarget*
|
||||
WorkerDebuggerGlobalScope::EventTargetFor(TaskCategory aCategory) const
|
||||
{
|
||||
return mSerialEventTarget;
|
||||
}
|
||||
|
||||
AbstractThread*
|
||||
WorkerDebuggerGlobalScope::AbstractMainThreadFor(TaskCategory aCategory)
|
||||
{
|
||||
MOZ_CRASH("AbstractMainThreadFor not supported for workers.");
|
||||
}
|
||||
|
||||
BEGIN_WORKERS_NAMESPACE
|
||||
|
||||
bool
|
||||
|
|
|
@ -58,6 +58,7 @@ class WorkerGlobalScope : public DOMEventTargetHelper,
|
|||
RefPtr<Performance> mPerformance;
|
||||
RefPtr<IDBFactory> mIndexedDB;
|
||||
RefPtr<cache::CacheStorage> mCacheStorage;
|
||||
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
|
||||
|
||||
uint32_t mWindowInteractionsAllowed;
|
||||
|
||||
|
@ -203,6 +204,18 @@ public:
|
|||
MOZ_ASSERT(mWindowInteractionsAllowed > 0);
|
||||
mWindowInteractionsAllowed--;
|
||||
}
|
||||
|
||||
// Override DispatchTrait API to target the worker thread. Dispatch may
|
||||
// return failure if the worker thread is not alive.
|
||||
nsresult
|
||||
Dispatch(const char* aName, TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable) override;
|
||||
|
||||
nsISerialEventTarget*
|
||||
EventTargetFor(TaskCategory aCategory) const override;
|
||||
|
||||
AbstractThread*
|
||||
AbstractMainThreadFor(TaskCategory aCategory) override;
|
||||
};
|
||||
|
||||
class DedicatedWorkerGlobalScope final : public WorkerGlobalScope
|
||||
|
@ -328,6 +341,7 @@ class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,
|
|||
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
RefPtr<Console> mConsole;
|
||||
nsCOMPtr<nsISerialEventTarget> mSerialEventTarget;
|
||||
|
||||
public:
|
||||
explicit WorkerDebuggerGlobalScope(WorkerPrivate* aWorkerPrivate);
|
||||
|
@ -404,6 +418,18 @@ public:
|
|||
void
|
||||
Dump(JSContext* aCx, const Optional<nsAString>& aString) const;
|
||||
|
||||
// Override DispatchTrait API to target the worker thread. Dispatch may
|
||||
// return failure if the worker thread is not alive.
|
||||
nsresult
|
||||
Dispatch(const char* aName, TaskCategory aCategory,
|
||||
already_AddRefed<nsIRunnable>&& aRunnable) override;
|
||||
|
||||
nsISerialEventTarget*
|
||||
EventTargetFor(TaskCategory aCategory) const override;
|
||||
|
||||
AbstractThread*
|
||||
AbstractMainThreadFor(TaskCategory aCategory) override;
|
||||
|
||||
private:
|
||||
virtual ~WorkerDebuggerGlobalScope();
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче