Bug 1690497 [wpt PR 27457] - Remove misleading contain-intrinsic-size prefix, a=testonly
[gecko.git] / image / DecodePool.cpp
blob4cecce0f9ccf7309ffc0a7baf4bc52b07f5e9af2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "DecodePool.h"
8 #include <algorithm>
10 #include "mozilla/ClearOnShutdown.h"
11 #include "mozilla/DebugOnly.h"
12 #include "mozilla/Monitor.h"
13 #include "mozilla/SchedulerGroup.h"
14 #include "mozilla/Services.h"
15 #include "mozilla/StaticPrefs_image.h"
16 #include "mozilla/TaskController.h"
17 #include "mozilla/TimeStamp.h"
18 #include "nsCOMPtr.h"
19 #include "nsIObserverService.h"
20 #include "nsThreadManager.h"
21 #include "nsThreadUtils.h"
22 #include "nsXPCOMCIDInternal.h"
23 #include "prsystem.h"
25 #include "Decoder.h"
26 #include "GeckoProfiler.h"
27 #include "IDecodingTask.h"
28 #include "RasterImage.h"
30 #if defined(XP_WIN)
31 # include <objbase.h>
32 #endif
34 using std::max;
35 using std::min;
37 namespace mozilla {
38 namespace image {
40 ///////////////////////////////////////////////////////////////////////////////
41 // DecodePool implementation.
42 ///////////////////////////////////////////////////////////////////////////////
44 /* static */
45 StaticRefPtr<DecodePool> DecodePool::sSingleton;
46 /* static */
47 uint32_t DecodePool::sNumCores = 0;
49 NS_IMPL_ISUPPORTS(DecodePool, nsIObserver)
51 /* static */
52 void DecodePool::Initialize() {
53 MOZ_ASSERT(NS_IsMainThread());
54 sNumCores = max<int32_t>(PR_GetNumberOfProcessors(), 1);
55 DecodePool::Singleton();
58 /* static */
59 DecodePool* DecodePool::Singleton() {
60 if (!sSingleton) {
61 MOZ_ASSERT(NS_IsMainThread());
62 sSingleton = new DecodePool();
63 ClearOnShutdown(&sSingleton);
66 return sSingleton;
69 /* static */
70 uint32_t DecodePool::NumberOfCores() { return sNumCores; }
72 #if defined(XP_WIN)
73 class IOThreadIniter final : public Runnable {
74 public:
75 explicit IOThreadIniter() : Runnable("image::IOThreadIniter") {}
77 NS_IMETHOD Run() override {
78 MOZ_ASSERT(!NS_IsMainThread());
80 CoInitialize(nullptr);
82 return NS_OK;
85 #endif
87 DecodePool::DecodePool() : mMutex("image::IOThread") {
88 // Initialize the I/O thread.
89 #if defined(XP_WIN)
90 // On Windows we use the io thread to get icons from the system. Any thread
91 // that makes system calls needs to call CoInitialize. And these system calls
92 // (SHGetFileInfo) should only be called from one thread at a time, in case
93 // we ever create more than on io thread.
94 nsCOMPtr<nsIRunnable> initer = new IOThreadIniter();
95 nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread), initer);
96 #else
97 nsresult rv = NS_NewNamedThread("ImageIO", getter_AddRefs(mIOThread));
98 #endif
99 MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv) && mIOThread,
100 "Should successfully create image I/O thread");
102 nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
103 if (obsSvc) {
104 obsSvc->AddObserver(this, "xpcom-shutdown-threads", false);
108 DecodePool::~DecodePool() {
109 MOZ_ASSERT(NS_IsMainThread(), "Must shut down DecodePool on main thread!");
112 NS_IMETHODIMP
113 DecodePool::Observe(nsISupports*, const char* aTopic, const char16_t*) {
114 MOZ_ASSERT(strcmp(aTopic, "xpcom-shutdown-threads") == 0, "Unexpected topic");
116 mShuttingDown = true;
118 nsCOMPtr<nsIThread> ioThread;
121 MutexAutoLock lock(mMutex);
122 ioThread.swap(mIOThread);
125 if (ioThread) {
126 ioThread->Shutdown();
129 return NS_OK;
132 bool DecodePool::IsShuttingDown() const { return mShuttingDown; }
134 class DecodingTask final : public Task {
135 public:
136 explicit DecodingTask(RefPtr<IDecodingTask>&& aTask)
137 : Task(false, aTask->Priority() == TaskPriority::eLow
138 ? EventQueuePriority::Normal
139 : EventQueuePriority::MediumHigh),
140 mTask(aTask) {}
142 bool Run() override {
143 mTask->Run();
144 return true;
147 private:
148 RefPtr<IDecodingTask> mTask;
151 void DecodePool::AsyncRun(IDecodingTask* aTask) {
152 MOZ_ASSERT(aTask);
154 TaskController::Get()->AddTask(
155 MakeAndAddRef<DecodingTask>((RefPtr<IDecodingTask>(aTask))));
158 bool DecodePool::SyncRunIfPreferred(IDecodingTask* aTask,
159 const nsCString& aURI) {
160 MOZ_ASSERT(NS_IsMainThread());
161 MOZ_ASSERT(aTask);
163 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPreferred",
164 GRAPHICS, aURI);
166 if (aTask->ShouldPreferSyncRun()) {
167 aTask->Run();
168 return true;
171 AsyncRun(aTask);
172 return false;
175 void DecodePool::SyncRunIfPossible(IDecodingTask* aTask,
176 const nsCString& aURI) {
177 MOZ_ASSERT(NS_IsMainThread());
178 MOZ_ASSERT(aTask);
180 AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING("DecodePool::SyncRunIfPossible",
181 GRAPHICS, aURI);
183 aTask->Run();
186 already_AddRefed<nsIEventTarget> DecodePool::GetIOEventTarget() {
187 MutexAutoLock threadPoolLock(mMutex);
188 nsCOMPtr<nsIEventTarget> target = mIOThread;
189 return target.forget();
192 } // namespace image
193 } // namespace mozilla