/* -*- 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/. */
// The C stack size. We use the same stack size on all platforms for // consistency. // // Note: Our typical equation of 256 machine words works out to 2MB on 64-bit // platforms. Since that works out to the size of a VM huge page, that can // sometimes lead to an OS allocating an entire huge page for the stack at once. // To avoid this, we subtract the size of 2 pages, to be safe. const uint32_t kWorkerStackSize = 256 * sizeof(size_t) * 1024 - 8192;
MOZ_ASSERT(mWorkerPrivate);
MOZ_ASSERT(!mAcceptingNonWorkerRunnables); // mOtherThreadsDispatchingViaEventTarget can still be non-zero here // because WorkerThread::Dispatch isn't atomic so a thread initiating // dispatch can have dispatched a runnable at this thread allowing us to // begin shutdown before that thread gets a chance to decrement // mOtherThreadsDispatchingViaEventTarget back to 0. So we need to wait // for that. while (mOtherThreadsDispatchingViaEventTarget) {
mWorkerPrivateCondVar.Wait();
} // Need to clean up the dispatched runnables if // mOtherThreadsDispatchingViaEventTarget was non-zero. if (NS_HasPendingEvents(nullptr)) {
NS_ProcessPendingEvents(nullptr);
} #ifdef DEBUG
mAcceptingNonWorkerRunnables = true; #endif
mWorkerPrivate = nullptr;
}
}
nsresult WorkerThread::DispatchAnyThread( const WorkerThreadFriendKey& /* aKey */,
RefPtr<WorkerRunnable> aWorkerRunnable) { // May be called on any thread!
// We don't need to notify the worker's condition variable here because we're // being called from worker-controlled code and it will make sure to wake up // the worker thread if needed.
NS_IMETHODIMP
WorkerThread::Dispatch(already_AddRefed<nsIRunnable> aRunnable,
uint32_t aFlags) { // May be called on any thread!
nsCOMPtr<nsIRunnable> runnable(aRunnable); // in case we exit early
WorkerPrivate* workerPrivate = nullptr; if (onWorkerThread) { // If the mWorkerPrivate has already disconnected by // WorkerPrivate::ResetWorkerPrivateInWorkerThread(), there is no chance // that to execute this runnable. Return NS_ERROR_UNEXPECTED here. if (!mWorkerPrivate) { return NS_ERROR_UNEXPECTED;
} // No need to lock here because it is only modified on this thread.
mWorkerPrivate->AssertIsOnWorkerThread();
if (mWorkerPrivate) {
workerPrivate = mWorkerPrivate;
// Incrementing this counter will make the worker thread sleep if it // somehow tries to unset mWorkerPrivate while we're using it.
mOtherThreadsDispatchingViaEventTarget++;
}
}
if (!onWorkerThread && workerPrivate) { // We need to wake the worker thread if we're not already on the right // thread and the dispatch succeeded. if (NS_SUCCEEDED(rv)) {
MutexAutoLock workerLock(workerPrivate->mMutex);
workerPrivate->mCondVar.Notify();
}
// Now unset our waiting flag.
{
MutexAutoLock lock(mLock);
NS_IMETHODIMP
WorkerThread::HasPendingEvents(bool* aResult) {
MOZ_ASSERT(aResult); constbool onWorkerThread = PR_GetCurrentThread() == mThread; // If is on the worker thread, call nsThread::HasPendingEvents directly. if (onWorkerThread) { return nsThread::HasPendingEvents(aResult);
} // Checking if is on the parent thread, otherwise, returns unexpected error.
{
MutexAutoLock lock(mLock); // return directly if the mWorkerPrivate has not yet set or had already // unset if (!mWorkerPrivate) {
*aResult = false; return NS_OK;
} if (!mWorkerPrivate->IsOnParentThread()) {
*aResult = false; return NS_ERROR_UNEXPECTED;
}
}
*aResult = mEvents->HasPendingEvent(); return NS_OK;
}
// If the PBackground child is not created yet, then we must permit // blocking event processing to support // BackgroundChild::GetOrCreateCreateForCurrentThread(). 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(CycleCollectedJSContext::Get()->RecursionDepth() == 2);
MOZ_ASSERT(!BackgroundChild::GetForCurrentThread()); return NS_OK;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.