diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /xpcom/threads/LazyIdleThread.cpp | |
parent | Initial commit. (diff) | |
download | firefox-esr-upstream/115.8.0esr.tar.xz firefox-esr-upstream/115.8.0esr.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xpcom/threads/LazyIdleThread.cpp')
-rw-r--r-- | xpcom/threads/LazyIdleThread.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/xpcom/threads/LazyIdleThread.cpp b/xpcom/threads/LazyIdleThread.cpp new file mode 100644 index 0000000000..4187fcc4ff --- /dev/null +++ b/xpcom/threads/LazyIdleThread.cpp @@ -0,0 +1,126 @@ +/* -*- 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 "LazyIdleThread.h" + +#include "nsIObserverService.h" +#include "nsServiceManagerUtils.h" +#include "nsThreadUtils.h" + +#ifdef DEBUG +# define ASSERT_OWNING_THREAD() \ + do { \ + MOZ_ASSERT(mOwningEventTarget->IsOnCurrentThread()); \ + } while (0) +#else +# define ASSERT_OWNING_THREAD() /* nothing */ +#endif + +namespace mozilla { + +LazyIdleThread::LazyIdleThread(uint32_t aIdleTimeoutMS, const char* aName, + ShutdownMethod aShutdownMethod) + : mOwningEventTarget(GetCurrentSerialEventTarget()), + mThreadPool(new nsThreadPool()), + mTaskQueue(TaskQueue::Create(do_AddRef(mThreadPool), aName)) { + // Configure the threadpool to host a single thread. It will be responsible + // for managing the thread's lifetime. + MOZ_ALWAYS_SUCCEEDS(mThreadPool->SetThreadLimit(1)); + MOZ_ALWAYS_SUCCEEDS(mThreadPool->SetIdleThreadLimit(1)); + MOZ_ALWAYS_SUCCEEDS(mThreadPool->SetIdleThreadTimeout(aIdleTimeoutMS)); + MOZ_ALWAYS_SUCCEEDS(mThreadPool->SetName(nsDependentCString(aName))); + + if (aShutdownMethod == ShutdownMethod::AutomaticShutdown && + NS_IsMainThread()) { + if (nsCOMPtr<nsIObserverService> obs = + do_GetService(NS_OBSERVERSERVICE_CONTRACTID)) { + MOZ_ALWAYS_SUCCEEDS( + obs->AddObserver(this, "xpcom-shutdown-threads", false)); + } + } +} + +static void LazyIdleThreadShutdown(nsThreadPool* aThreadPool, + TaskQueue* aTaskQueue) { + aTaskQueue->BeginShutdown(); + aTaskQueue->AwaitShutdownAndIdle(); + aThreadPool->Shutdown(); +} + +LazyIdleThread::~LazyIdleThread() { + if (!mShutdown) { + mOwningEventTarget->Dispatch(NS_NewRunnableFunction( + "LazyIdleThread::~LazyIdleThread", + [threadPool = mThreadPool, taskQueue = mTaskQueue] { + LazyIdleThreadShutdown(threadPool, taskQueue); + })); + } +} + +void LazyIdleThread::Shutdown() { + ASSERT_OWNING_THREAD(); + + if (!mShutdown) { + mShutdown = true; + LazyIdleThreadShutdown(mThreadPool, mTaskQueue); + } +} + +nsresult LazyIdleThread::SetListener(nsIThreadPoolListener* aListener) { + return mThreadPool->SetListener(aListener); +} + +NS_IMPL_ISUPPORTS(LazyIdleThread, nsIEventTarget, nsISerialEventTarget, + nsIObserver) + +NS_IMETHODIMP +LazyIdleThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags) { + nsCOMPtr<nsIRunnable> event(aEvent); + return Dispatch(event.forget(), aFlags); +} + +NS_IMETHODIMP +LazyIdleThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, + uint32_t aFlags) { + return mTaskQueue->Dispatch(std::move(aEvent), aFlags); +} + +NS_IMETHODIMP +LazyIdleThread::DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +LazyIdleThread::RegisterShutdownTask(nsITargetShutdownTask* aTask) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +LazyIdleThread::UnregisterShutdownTask(nsITargetShutdownTask* aTask) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +LazyIdleThread::IsOnCurrentThread(bool* aIsOnCurrentThread) { + return mTaskQueue->IsOnCurrentThread(aIsOnCurrentThread); +} + +NS_IMETHODIMP_(bool) +LazyIdleThread::IsOnCurrentThreadInfallible() { + return mTaskQueue->IsOnCurrentThreadInfallible(); +} + +NS_IMETHODIMP +LazyIdleThread::Observe(nsISupports* /* aSubject */, const char* aTopic, + const char16_t* /* aData */) { + MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); + MOZ_ASSERT(!strcmp("xpcom-shutdown-threads", aTopic), "Bad topic!"); + + Shutdown(); + return NS_OK; +} + +} // namespace mozilla |