зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1054638 - Move WorkerThread into its own file, r=khuey.
This commit is contained in:
Родитель
793516eb34
Коммит
c8b921018d
|
@ -26,6 +26,7 @@
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "mozilla/CycleCollectedJSRuntime.h"
|
#include "mozilla/CycleCollectedJSRuntime.h"
|
||||||
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/dom/asmjscache/AsmJSCache.h"
|
#include "mozilla/dom/asmjscache/AsmJSCache.h"
|
||||||
#include "mozilla/dom/AtomList.h"
|
#include "mozilla/dom/AtomList.h"
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
@ -45,7 +46,6 @@
|
||||||
#include "nsLayoutStatics.h"
|
#include "nsLayoutStatics.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
#include "nsThread.h"
|
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsXPCOM.h"
|
#include "nsXPCOM.h"
|
||||||
#include "nsXPCOMPrivate.h"
|
#include "nsXPCOMPrivate.h"
|
||||||
|
@ -56,15 +56,12 @@
|
||||||
#include "ipc/Nuwa.h"
|
#include "ipc/Nuwa.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#include "nsThreadManager.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "Principal.h"
|
#include "Principal.h"
|
||||||
#include "ServiceWorker.h"
|
#include "ServiceWorker.h"
|
||||||
#include "SharedWorker.h"
|
#include "SharedWorker.h"
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
#include "WorkerRunnable.h"
|
#include "WorkerRunnable.h"
|
||||||
|
#include "WorkerThread.h"
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
#include "BackgroundChildImpl.h"
|
#include "BackgroundChildImpl.h"
|
||||||
|
@ -90,10 +87,6 @@ using mozilla::Preferences;
|
||||||
// The size of the worker JS allocation threshold in MB. May be changed via pref.
|
// The size of the worker JS allocation threshold in MB. May be changed via pref.
|
||||||
#define WORKER_DEFAULT_ALLOCATION_THRESHOLD 30
|
#define WORKER_DEFAULT_ALLOCATION_THRESHOLD 30
|
||||||
|
|
||||||
// The C stack size. We use the same stack size on all platforms for
|
|
||||||
// consistency.
|
|
||||||
#define WORKER_STACK_SIZE 256 * sizeof(size_t) * 1024
|
|
||||||
|
|
||||||
// Half the size of the actual C stack, to be safe.
|
// Half the size of the actual C stack, to be safe.
|
||||||
#define WORKER_CONTEXT_NATIVE_STACK_LIMIT 128 * sizeof(size_t) * 1024
|
#define WORKER_CONTEXT_NATIVE_STACK_LIMIT 128 * sizeof(size_t) * 1024
|
||||||
|
|
||||||
|
@ -907,6 +900,58 @@ private:
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_TESTS
|
||||||
|
|
||||||
|
class TestPBackgroundCreateCallback MOZ_FINAL :
|
||||||
|
public nsIIPCBackgroundChildCreateCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
ActorCreated(PBackgroundChild* aActor) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
MOZ_RELEASE_ASSERT(aActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void
|
||||||
|
ActorFailed() MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
MOZ_CRASH("TestPBackground() should not fail "
|
||||||
|
"GetOrCreateForCurrentThread()");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~TestPBackgroundCreateCallback()
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(TestPBackgroundCreateCallback,
|
||||||
|
nsIIPCBackgroundChildCreateCallback);
|
||||||
|
|
||||||
|
void
|
||||||
|
TestPBackground()
|
||||||
|
{
|
||||||
|
using namespace mozilla::ipc;
|
||||||
|
|
||||||
|
if (gTestPBackground) {
|
||||||
|
// Randomize value to validate workers are not cross-posting messages.
|
||||||
|
uint32_t testValue;
|
||||||
|
size_t randomSize = PR_GetRandomNoise(&testValue, sizeof(testValue));
|
||||||
|
MOZ_RELEASE_ASSERT(randomSize == sizeof(testValue));
|
||||||
|
nsCString testStr;
|
||||||
|
testStr.AppendInt(testValue);
|
||||||
|
testStr.AppendInt(reinterpret_cast<int64_t>(PR_GetCurrentThread()));
|
||||||
|
PBackgroundChild* existingBackgroundChild =
|
||||||
|
BackgroundChild::GetForCurrentThread();
|
||||||
|
MOZ_RELEASE_ASSERT(existingBackgroundChild);
|
||||||
|
bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr);
|
||||||
|
MOZ_RELEASE_ASSERT(ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ENABLE_TESTS
|
||||||
|
|
||||||
class WorkerBackgroundChildCallback MOZ_FINAL :
|
class WorkerBackgroundChildCallback MOZ_FINAL :
|
||||||
public nsIIPCBackgroundChildCreateCallback
|
public nsIIPCBackgroundChildCreateCallback
|
||||||
{
|
{
|
||||||
|
@ -942,15 +987,15 @@ private:
|
||||||
class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
|
class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
|
||||||
{
|
{
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
nsRefPtr<RuntimeService::WorkerThread> mThread;
|
nsRefPtr<WorkerThread> mThread;
|
||||||
JSRuntime* mParentRuntime;
|
JSRuntime* mParentRuntime;
|
||||||
|
|
||||||
class FinishedRunnable MOZ_FINAL : public nsRunnable
|
class FinishedRunnable MOZ_FINAL : public nsRunnable
|
||||||
{
|
{
|
||||||
nsRefPtr<RuntimeService::WorkerThread> mThread;
|
nsRefPtr<WorkerThread> mThread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FinishedRunnable(already_AddRefed<RuntimeService::WorkerThread> aThread)
|
explicit FinishedRunnable(already_AddRefed<WorkerThread> aThread)
|
||||||
: mThread(aThread)
|
: mThread(aThread)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mThread);
|
MOZ_ASSERT(mThread);
|
||||||
|
@ -967,7 +1012,7 @@ class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WorkerThreadPrimaryRunnable(WorkerPrivate* aWorkerPrivate,
|
WorkerThreadPrimaryRunnable(WorkerPrivate* aWorkerPrivate,
|
||||||
RuntimeService::WorkerThread* aThread,
|
WorkerThread* aThread,
|
||||||
JSRuntime* aParentRuntime)
|
JSRuntime* aParentRuntime)
|
||||||
: mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentRuntime(aParentRuntime)
|
: mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentRuntime(aParentRuntime)
|
||||||
{
|
{
|
||||||
|
@ -1078,129 +1123,6 @@ PlatformOverrideChanged(const char* /* aPrefName */, void* /* aClosure */)
|
||||||
|
|
||||||
} /* anonymous namespace */
|
} /* anonymous namespace */
|
||||||
|
|
||||||
class RuntimeService::WorkerThread MOZ_FINAL : public nsThread
|
|
||||||
{
|
|
||||||
class Observer MOZ_FINAL : public nsIThreadObserver
|
|
||||||
{
|
|
||||||
WorkerPrivate* mWorkerPrivate;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit Observer(WorkerPrivate* aWorkerPrivate)
|
|
||||||
: mWorkerPrivate(aWorkerPrivate)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aWorkerPrivate);
|
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
|
||||||
|
|
||||||
private:
|
|
||||||
~Observer()
|
|
||||||
{
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_NSITHREADOBSERVER
|
|
||||||
};
|
|
||||||
|
|
||||||
WorkerPrivate* mWorkerPrivate;
|
|
||||||
nsRefPtr<Observer> mObserver;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
// Protected by nsThread::mLock.
|
|
||||||
bool mAcceptingNonWorkerRunnables;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
static already_AddRefed<WorkerThread>
|
|
||||||
Create();
|
|
||||||
|
|
||||||
void
|
|
||||||
SetWorker(WorkerPrivate* aWorkerPrivate);
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
|
|
||||||
NS_IMETHOD
|
|
||||||
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
bool
|
|
||||||
IsAcceptingNonWorkerRunnables()
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(mLock);
|
|
||||||
return mAcceptingNonWorkerRunnables;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetAcceptingNonWorkerRunnables(bool aAcceptingNonWorkerRunnables)
|
|
||||||
{
|
|
||||||
MutexAutoLock lock(mLock);
|
|
||||||
mAcceptingNonWorkerRunnables = aAcceptingNonWorkerRunnables;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
|
||||||
class TestPBackgroundCreateCallback MOZ_FINAL :
|
|
||||||
public nsIIPCBackgroundChildCreateCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void ActorCreated(PBackgroundChild* actor) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_RELEASE_ASSERT(actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void ActorFailed() MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_CRASH("TestPBackground() should not fail GetOrCreateForCurrentThread()");
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
~TestPBackgroundCreateCallback()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
TestPBackground()
|
|
||||||
{
|
|
||||||
using namespace mozilla::ipc;
|
|
||||||
if (gTestPBackground) {
|
|
||||||
// Randomize value to validate workers are not cross-posting messages.
|
|
||||||
uint32_t testValue;
|
|
||||||
size_t randomSize = PR_GetRandomNoise(&testValue, sizeof(testValue));
|
|
||||||
MOZ_RELEASE_ASSERT(randomSize == sizeof(testValue));
|
|
||||||
nsCString testStr;
|
|
||||||
testStr.AppendInt(testValue);
|
|
||||||
testStr.AppendInt(reinterpret_cast<int64_t>(PR_GetCurrentThread()));
|
|
||||||
PBackgroundChild* existingBackgroundChild =
|
|
||||||
BackgroundChild::GetForCurrentThread();
|
|
||||||
MOZ_RELEASE_ASSERT(existingBackgroundChild);
|
|
||||||
bool ok = existingBackgroundChild->SendPBackgroundTestConstructor(testStr);
|
|
||||||
MOZ_RELEASE_ASSERT(ok);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // #ENABLE_TESTS
|
|
||||||
|
|
||||||
private:
|
|
||||||
WorkerThread()
|
|
||||||
: nsThread(nsThread::NOT_MAIN_THREAD, WORKER_STACK_SIZE),
|
|
||||||
mWorkerPrivate(nullptr)
|
|
||||||
#ifdef DEBUG
|
|
||||||
, mAcceptingNonWorkerRunnables(true)
|
|
||||||
#endif
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~WorkerThread()
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
|
||||||
NS_IMPL_ISUPPORTS(RuntimeService::WorkerThread::TestPBackgroundCreateCallback,
|
|
||||||
nsIIPCBackgroundChildCreateCallback);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BEGIN_WORKERS_NAMESPACE
|
BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1307,6 +1229,12 @@ GetCurrentThreadJSContext()
|
||||||
|
|
||||||
END_WORKERS_NAMESPACE
|
END_WORKERS_NAMESPACE
|
||||||
|
|
||||||
|
struct RuntimeService::IdleThreadInfo
|
||||||
|
{
|
||||||
|
nsRefPtr<WorkerThread> mThread;
|
||||||
|
mozilla::TimeStamp mExpirationTime;
|
||||||
|
};
|
||||||
|
|
||||||
// This is only touched on the main thread. Initialized in Init() below.
|
// This is only touched on the main thread. Initialized in Init() below.
|
||||||
JSSettings RuntimeService::sDefaultJSSettings;
|
JSSettings RuntimeService::sDefaultJSSettings;
|
||||||
bool RuntimeService::sDefaultPreferences[WORKERPREF_COUNT] = { false };
|
bool RuntimeService::sDefaultPreferences[WORKERPREF_COUNT] = { false };
|
||||||
|
@ -2592,145 +2520,6 @@ RuntimeService::JSVersionChanged(const char* /* aPrefName */, void* /* aClosure
|
||||||
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
|
options.setVersion(useLatest ? JSVERSION_LATEST : JSVERSION_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
already_AddRefed<RuntimeService::WorkerThread>
|
|
||||||
RuntimeService::WorkerThread::Create()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(nsThreadManager::get());
|
|
||||||
|
|
||||||
nsRefPtr<WorkerThread> thread = new WorkerThread();
|
|
||||||
if (NS_FAILED(thread->Init())) {
|
|
||||||
NS_WARNING("Failed to create new thread!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_SetThreadName(thread, "DOM Worker");
|
|
||||||
|
|
||||||
return thread.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
RuntimeService::WorkerThread::SetWorker(WorkerPrivate* aWorkerPrivate)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(PR_GetCurrentThread() == mThread);
|
|
||||||
MOZ_ASSERT_IF(aWorkerPrivate, !mWorkerPrivate);
|
|
||||||
MOZ_ASSERT_IF(!aWorkerPrivate, mWorkerPrivate);
|
|
||||||
|
|
||||||
// No need to lock here because mWorkerPrivate is only modified on mThread.
|
|
||||||
|
|
||||||
if (mWorkerPrivate) {
|
|
||||||
MOZ_ASSERT(mObserver);
|
|
||||||
|
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(RemoveObserver(mObserver)));
|
|
||||||
|
|
||||||
mObserver = nullptr;
|
|
||||||
mWorkerPrivate->SetThread(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
mWorkerPrivate = aWorkerPrivate;
|
|
||||||
|
|
||||||
if (mWorkerPrivate) {
|
|
||||||
mWorkerPrivate->SetThread(this);
|
|
||||||
|
|
||||||
nsRefPtr<Observer> observer = new Observer(mWorkerPrivate);
|
|
||||||
|
|
||||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(AddObserver(observer)));
|
|
||||||
|
|
||||||
mObserver.swap(observer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(RuntimeService::WorkerThread, nsThread)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
RuntimeService::WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
|
|
||||||
{
|
|
||||||
// May be called on any thread!
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (PR_GetCurrentThread() == mThread) {
|
|
||||||
MOZ_ASSERT(mWorkerPrivate);
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
}
|
|
||||||
else if (aRunnable && !IsAcceptingNonWorkerRunnables()) {
|
|
||||||
// Only enforce cancelable runnables after we've started the worker loop.
|
|
||||||
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
|
|
||||||
MOZ_ASSERT(cancelable,
|
|
||||||
"Should have been wrapped by the worker's event target!");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Workers only support asynchronous dispatch for now.
|
|
||||||
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIRunnable* runnableToDispatch;
|
|
||||||
nsRefPtr<WorkerRunnable> workerRunnable;
|
|
||||||
|
|
||||||
if (aRunnable && PR_GetCurrentThread() == mThread) {
|
|
||||||
// No need to lock here because mWorkerPrivate is only modified on mThread.
|
|
||||||
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
|
|
||||||
runnableToDispatch = workerRunnable;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
runnableToDispatch = aRunnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = nsThread::Dispatch(runnableToDispatch, NS_DISPATCH_NORMAL);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(RuntimeService::WorkerThread::Observer, nsIThreadObserver)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
RuntimeService::WorkerThread::Observer::OnDispatchedEvent(
|
|
||||||
nsIThreadInternal* /*aThread */)
|
|
||||||
{
|
|
||||||
MOZ_CRASH("OnDispatchedEvent() should never be called!");
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
RuntimeService::WorkerThread::Observer::OnProcessNextEvent(
|
|
||||||
nsIThreadInternal* /* aThread */,
|
|
||||||
bool aMayWait,
|
|
||||||
uint32_t aRecursionDepth)
|
|
||||||
{
|
|
||||||
using mozilla::ipc::BackgroundChild;
|
|
||||||
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
|
|
||||||
// If the PBackground child is not created yet, then we must permit
|
|
||||||
// blocking event processing to support SynchronouslyCreatePBackground().
|
|
||||||
// If this occurs then we are spinning on the event queue at the start of
|
|
||||||
// PrimaryWorkerRunnable::Run() and don't want to process the event in
|
|
||||||
// mWorkerPrivate yet.
|
|
||||||
if (aMayWait) {
|
|
||||||
MOZ_ASSERT(aRecursionDepth == 2);
|
|
||||||
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
RuntimeService::WorkerThread::Observer::AfterProcessNextEvent(
|
|
||||||
nsIThreadInternal* /* aThread */,
|
|
||||||
uint32_t aRecursionDepth,
|
|
||||||
bool /* aEventWasProcessed */)
|
|
||||||
{
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
|
||||||
|
|
||||||
mWorkerPrivate->AfterProcessNextEvent(aRecursionDepth);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(LogViolationDetailsRunnable, nsRunnable)
|
NS_IMPL_ISUPPORTS_INHERITED0(LogViolationDetailsRunnable, nsRunnable)
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -2796,7 +2585,7 @@ WorkerThreadPrimaryRunnable::Run()
|
||||||
mThread->SetWorker(mWorkerPrivate);
|
mThread->SetWorker(mWorkerPrivate);
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
mThread->TestPBackground();
|
TestPBackground();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mWorkerPrivate->AssertIsOnWorkerThread();
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
@ -2831,7 +2620,7 @@ WorkerThreadPrimaryRunnable::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
mThread->TestPBackground();
|
TestPBackground();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BackgroundChild::CloseForCurrentThread();
|
BackgroundChild::CloseForCurrentThread();
|
||||||
|
@ -2914,7 +2703,7 @@ WorkerThreadPrimaryRunnable::FinishedRunnable::Run()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
nsRefPtr<RuntimeService::WorkerThread> thread;
|
nsRefPtr<WorkerThread> thread;
|
||||||
mThread.swap(thread);
|
mThread.swap(thread);
|
||||||
|
|
||||||
RuntimeService* rts = RuntimeService::GetService();
|
RuntimeService* rts = RuntimeService::GetService();
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
|
||||||
#include "mozilla/TimeStamp.h"
|
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
|
@ -20,7 +19,6 @@
|
||||||
#include "WorkerPrivate.h"
|
#include "WorkerPrivate.h"
|
||||||
|
|
||||||
class nsIRunnable;
|
class nsIRunnable;
|
||||||
class nsIThread;
|
|
||||||
class nsITimer;
|
class nsITimer;
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
|
|
||||||
|
@ -28,13 +26,10 @@ BEGIN_WORKERS_NAMESPACE
|
||||||
|
|
||||||
class ServiceWorker;
|
class ServiceWorker;
|
||||||
class SharedWorker;
|
class SharedWorker;
|
||||||
|
class WorkerThread;
|
||||||
|
|
||||||
class RuntimeService MOZ_FINAL : public nsIObserver
|
class RuntimeService MOZ_FINAL : public nsIObserver
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
class WorkerThread;
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct SharedWorkerInfo
|
struct SharedWorkerInfo
|
||||||
{
|
{
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
|
@ -67,11 +62,7 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IdleThreadInfo
|
struct IdleThreadInfo;
|
||||||
{
|
|
||||||
nsRefPtr<WorkerThread> mThread;
|
|
||||||
mozilla::TimeStamp mExpirationTime;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MatchSharedWorkerInfo
|
struct MatchSharedWorkerInfo
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* vim: set ts=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 "WorkerThread.h"
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/ipc/BackgroundChild.h"
|
||||||
|
#include "nsIThreadInternal.h"
|
||||||
|
#include "WorkerPrivate.h"
|
||||||
|
#include "WorkerRunnable.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include "nsThreadManager.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace workers {
|
||||||
|
|
||||||
|
using namespace mozilla::ipc;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// The C stack size. We use the same stack size on all platforms for
|
||||||
|
// consistency.
|
||||||
|
const uint32_t kWorkerStackSize = 256 * sizeof(size_t) * 1024;
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
class WorkerThread::Observer MOZ_FINAL
|
||||||
|
: public nsIThreadObserver
|
||||||
|
{
|
||||||
|
WorkerPrivate* mWorkerPrivate;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Observer(WorkerPrivate* aWorkerPrivate)
|
||||||
|
: mWorkerPrivate(aWorkerPrivate)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWorkerPrivate);
|
||||||
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
|
||||||
|
private:
|
||||||
|
~Observer()
|
||||||
|
{
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_DECL_NSITHREADOBSERVER
|
||||||
|
};
|
||||||
|
|
||||||
|
WorkerThread::WorkerThread()
|
||||||
|
: nsThread(nsThread::NOT_MAIN_THREAD, kWorkerStackSize),
|
||||||
|
mWorkerPrivate(nullptr)
|
||||||
|
#ifdef DEBUG
|
||||||
|
, mAcceptingNonWorkerRunnables(true)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerThread::~WorkerThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
already_AddRefed<WorkerThread>
|
||||||
|
WorkerThread::Create()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(nsThreadManager::get());
|
||||||
|
|
||||||
|
nsRefPtr<WorkerThread> thread = new WorkerThread();
|
||||||
|
if (NS_FAILED(thread->Init())) {
|
||||||
|
NS_WARNING("Failed to create new thread!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_SetThreadName(thread, "DOM Worker");
|
||||||
|
|
||||||
|
return thread.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WorkerThread::SetWorker(WorkerPrivate* aWorkerPrivate)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == mThread);
|
||||||
|
MOZ_ASSERT_IF(aWorkerPrivate, !mWorkerPrivate);
|
||||||
|
MOZ_ASSERT_IF(!aWorkerPrivate, mWorkerPrivate);
|
||||||
|
|
||||||
|
// No need to lock here because mWorkerPrivate is only modified on mThread.
|
||||||
|
|
||||||
|
if (mWorkerPrivate) {
|
||||||
|
MOZ_ASSERT(mObserver);
|
||||||
|
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(RemoveObserver(mObserver)));
|
||||||
|
|
||||||
|
mObserver = nullptr;
|
||||||
|
mWorkerPrivate->SetThread(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mWorkerPrivate = aWorkerPrivate;
|
||||||
|
|
||||||
|
if (mWorkerPrivate) {
|
||||||
|
mWorkerPrivate->SetThread(this);
|
||||||
|
|
||||||
|
nsRefPtr<Observer> observer = new Observer(mWorkerPrivate);
|
||||||
|
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(AddObserver(observer)));
|
||||||
|
|
||||||
|
mObserver.swap(observer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS_INHERITED0(WorkerThread, nsThread)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WorkerThread::Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
|
||||||
|
{
|
||||||
|
// May be called on any thread!
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (PR_GetCurrentThread() == mThread) {
|
||||||
|
MOZ_ASSERT(mWorkerPrivate);
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
}
|
||||||
|
else if (aRunnable && !IsAcceptingNonWorkerRunnables()) {
|
||||||
|
// Only enforce cancelable runnables after we've started the worker loop.
|
||||||
|
nsCOMPtr<nsICancelableRunnable> cancelable = do_QueryInterface(aRunnable);
|
||||||
|
MOZ_ASSERT(cancelable,
|
||||||
|
"Should have been wrapped by the worker's event target!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Workers only support asynchronous dispatch for now.
|
||||||
|
if (NS_WARN_IF(aFlags != NS_DISPATCH_NORMAL)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIRunnable* runnableToDispatch;
|
||||||
|
nsRefPtr<WorkerRunnable> workerRunnable;
|
||||||
|
|
||||||
|
if (aRunnable && PR_GetCurrentThread() == mThread) {
|
||||||
|
// No need to lock here because mWorkerPrivate is only modified on mThread.
|
||||||
|
workerRunnable = mWorkerPrivate->MaybeWrapAsWorkerRunnable(aRunnable);
|
||||||
|
runnableToDispatch = workerRunnable;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
runnableToDispatch = aRunnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult rv = nsThread::Dispatch(runnableToDispatch, NS_DISPATCH_NORMAL);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(WorkerThread::Observer, nsIThreadObserver)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WorkerThread::Observer::OnDispatchedEvent(nsIThreadInternal* /* aThread */)
|
||||||
|
{
|
||||||
|
MOZ_CRASH("OnDispatchedEvent() should never be called!");
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WorkerThread::Observer::OnProcessNextEvent(nsIThreadInternal* /* aThread */,
|
||||||
|
bool aMayWait,
|
||||||
|
uint32_t aRecursionDepth)
|
||||||
|
{
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
// If the PBackground child is not created yet, then we must permit
|
||||||
|
// blocking event processing to support SynchronouslyCreatePBackground().
|
||||||
|
// If this occurs then we are spinning on the event queue at the start of
|
||||||
|
// PrimaryWorkerRunnable::Run() and don't want to process the event in
|
||||||
|
// mWorkerPrivate yet.
|
||||||
|
if (aMayWait) {
|
||||||
|
MOZ_ASSERT(aRecursionDepth == 2);
|
||||||
|
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWorkerPrivate->OnProcessNextEvent(aRecursionDepth);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WorkerThread::Observer::AfterProcessNextEvent(nsIThreadInternal* /* aThread */,
|
||||||
|
uint32_t aRecursionDepth,
|
||||||
|
bool /* aEventWasProcessed */)
|
||||||
|
{
|
||||||
|
mWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
mWorkerPrivate->AfterProcessNextEvent(aRecursionDepth);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace workers
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,76 @@
|
||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* vim: set ts=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_workers_WorkerThread_h__
|
||||||
|
#define mozilla_dom_workers_WorkerThread_h__
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/DebugOnly.h"
|
||||||
|
#include "nsISupportsImpl.h"
|
||||||
|
#include "nsRefPtr.h"
|
||||||
|
#include "nsThread.h"
|
||||||
|
|
||||||
|
class nsIRunnable;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace workers {
|
||||||
|
|
||||||
|
class WorkerPrivate;
|
||||||
|
class WorkerRunnable;
|
||||||
|
|
||||||
|
class WorkerThread MOZ_FINAL
|
||||||
|
: public nsThread
|
||||||
|
{
|
||||||
|
class Observer;
|
||||||
|
|
||||||
|
WorkerPrivate* mWorkerPrivate;
|
||||||
|
nsRefPtr<Observer> mObserver;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Protected by nsThread::mLock.
|
||||||
|
bool mAcceptingNonWorkerRunnables;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
static already_AddRefed<WorkerThread>
|
||||||
|
Create();
|
||||||
|
|
||||||
|
void
|
||||||
|
SetWorker(WorkerPrivate* aWorkerPrivate);
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Dispatch(nsIRunnable* aRunnable, uint32_t aFlags) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool
|
||||||
|
IsAcceptingNonWorkerRunnables()
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mLock);
|
||||||
|
return mAcceptingNonWorkerRunnables;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetAcceptingNonWorkerRunnables(bool aAcceptingNonWorkerRunnables)
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mLock);
|
||||||
|
mAcceptingNonWorkerRunnables = aAcceptingNonWorkerRunnables;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
WorkerThread();
|
||||||
|
|
||||||
|
~WorkerThread();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace workers
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_workers_WorkerThread_h__
|
|
@ -72,6 +72,7 @@ UNIFIED_SOURCES += [
|
||||||
'WorkerPrivate.cpp',
|
'WorkerPrivate.cpp',
|
||||||
'WorkerRunnable.cpp',
|
'WorkerRunnable.cpp',
|
||||||
'WorkerScope.cpp',
|
'WorkerScope.cpp',
|
||||||
|
'WorkerThread.cpp',
|
||||||
'XMLHttpRequest.cpp',
|
'XMLHttpRequest.cpp',
|
||||||
'XMLHttpRequestUpload.cpp',
|
'XMLHttpRequestUpload.cpp',
|
||||||
]
|
]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче