diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /image/DecodePool.cpp | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'image/DecodePool.cpp')
-rw-r--r-- | image/DecodePool.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/image/DecodePool.cpp b/image/DecodePool.cpp new file mode 100644 index 0000000000..4cecce0f9c --- /dev/null +++ b/image/DecodePool.cpp @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "DecodePool.h" + +#include <algorithm> + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/Monitor.h" +#include "mozilla/SchedulerGroup.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPrefs_image.h" +#include "mozilla/TaskController.h" +#include "mozilla/TimeStamp.h" +#include "nsCOMPtr.h" +#include "nsIObserverService.h" +#include "nsThreadManager.h" +#include "nsThreadUtils.h" +#include "nsXPCOMCIDInternal.h" +#include "prsystem.h" + +#include "Decoder.h" +#include "GeckoProfiler.h" +#include "IDecodingTask.h" +#include "RasterImage.h" + +#if defined(XP_WIN) +# include <objbase.h> +#endif + +using std::max; +using std::min; + +namespace mozilla { +namespace image { + +/////////////////////////////////////////////////////////////////////////////// +// DecodePool implementation. +/////////////////////////////////////////////////////////////////////////////// + +/* static */ +StaticRefPtr<DecodePool> DecodePool::sSingleton; +/* static */ +uint32_t DecodePool::sNumCores = 0; + +NS_IMPL_ISUPPORTS(DecodePool, nsIObserver) + +/* static */ +void DecodePool::Initialize() { + MOZ_ASSERT(NS_IsMainThread()); + sNumCores = max<int32_t>(PR_GetNumberOfProcessors(), 1); + DecodePool::Singleton(); +} + +/* static */ +DecodePool* DecodePool::Singleton() { + if (!sSingleton) { + MOZ_ASSERT(NS_IsMainThread()); + sSingleton = new DecodePool(); + ClearOnShutdown(&sSingleton); + } + + return sSingleton; +} + +/* static */ +uint32_t DecodePool::NumberOfCores() { return sNumCores; } + +#if defined(XP_WIN) +class IOThreadIniter final : public Runnable { + public: + explicit IOThreadIniter() : Runnable("image::IOThreadIniter") {} + + NS_IMETHOD Run() override { + MOZ_ASSERT(!NS_IsMainThread()); + + CoInitialize(nullptr); + + return NS_OK; + } +}; +#endif + +DecodePool::DecodePool() : mMutex("image::IOThread") { + // Initialize the I/O thread. +#if defined(XP_WIN) + // On Windows we use the io thread to get icons from the system. Any thread + // that makes system calls needs to call CoInitialize. And these system calls + // (SHGetFileInfo) should only be called from one thread at a time, in case + // we ever create more than on io thread. + nsCOMPtr<nsIRunnable> initer = new IOThreadIniter(); + nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread), initer); +#else + nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread)); +#endif + MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread, + "Should successfully create image I/O thread"); + + nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService(); + if (obsSvc) { + obsSvc->AddObserver(this, "xpcom-shutdown-threads", false); + } +} + +DecodePool::~DecodePool() { + MOZ_ASSERT(NS_IsMainThread(), "Must shut down DecodePool on main thread!"); +} + +NS_IMETHODIMP +DecodePool::Observe(nsISupports*, const char* aTopic, const char16_t*) { + MOZ_ASSERT(strcmp(aTopic, "xpcom-shutdown-threads") == 0, "Unexpected topic"); + + mShuttingDown = true; + + nsCOMPtr<nsIThread> ioThread; + + { + MutexAutoLock lock(mMutex); + ioThread.swap(mIOThread); + } + + if (ioThread) { + ioThread->Shutdown(); + } + + return NS_OK; +} + +bool DecodePool::IsShuttingDown() const { return mShuttingDown; } + +class DecodingTask final : public Task { + public: + explicit DecodingTask(RefPtr<IDecodingTask>&& aTask) + : Task(false, aTask->Priority() == TaskPriority::eLow + ? EventQueuePriority::Normal + : EventQueuePriority::MediumHigh), + mTask(aTask) {} + + bool Run() override { + mTask->Run(); + return true; + } + + private: + RefPtr<IDecodingTask> mTask; +}; + +void DecodePool::AsyncRun(IDecodingTask* aTask) { + MOZ_ASSERT(aTask); + + TaskController::Get()->AddTask( + MakeAndAddRef<DecodingTask>((RefPtr<IDecodingTask>(aTask)))); +} + +bool DecodePool::SyncRunIfPreferred(IDecodingTask* aTask, + const nsCString& aURI) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aTask); + + AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPreferred", + GRAPHICS, aURI); + + if (aTask->ShouldPreferSyncRun()) { + aTask->Run(); + return true; + } + + AsyncRun(aTask); + return false; +} + +void DecodePool::SyncRunIfPossible(IDecodingTask* aTask, + const nsCString& aURI) { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(aTask); + + AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPossible", + GRAPHICS, aURI); + + aTask->Run(); +} + +already_AddRefed<nsIEventTarget> DecodePool::GetIOEventTarget() { + MutexAutoLock threadPoolLock(mMutex); + nsCOMPtr<nsIEventTarget> target = mIOThread; + return target.forget(); +} + +} // namespace image +} // namespace mozilla |