Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.cpp

Issue 2618893002: Fix memory leak with ScriptedIdleTaskController (Closed)
Patch Set: Improve test Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/dom/ScriptedIdleTaskController.h" 5 #include "core/dom/ScriptedIdleTaskController.h"
6 6
7 #include "core/dom/ExecutionContext.h" 7 #include "core/dom/ExecutionContext.h"
8 #include "core/dom/IdleRequestCallback.h" 8 #include "core/dom/IdleRequestCallback.h"
9 #include "core/dom/IdleRequestOptions.h" 9 #include "core/dom/IdleRequestOptions.h"
10 #include "core/frame/PerformanceMonitor.h" 10 #include "core/frame/PerformanceMonitor.h"
11 #include "core/inspector/InspectorTraceEvents.h" 11 #include "core/inspector/InspectorTraceEvents.h"
12 #include "platform/Histogram.h" 12 #include "platform/Histogram.h"
13 #include "platform/instrumentation/tracing/TraceEvent.h" 13 #include "platform/instrumentation/tracing/TraceEvent.h"
14 #include "public/platform/Platform.h" 14 #include "public/platform/Platform.h"
15 #include "public/platform/WebScheduler.h" 15 #include "public/platform/WebScheduler.h"
16 #include "public/platform/WebTraceLocation.h" 16 #include "public/platform/WebTraceLocation.h"
17 #include "wtf/CurrentTime.h" 17 #include "wtf/CurrentTime.h"
18 #include "wtf/Functional.h" 18 #include "wtf/Functional.h"
19 #include "wtf/RefCounted.h" 19 #include "wtf/RefCounted.h"
20 20
21 namespace blink { 21 namespace blink {
22 22
23 namespace internal { 23 namespace internal {
24 24
25 class IdleRequestCallbackWrapper 25 class IdleRequestCallbackWrapper
26 : public RefCounted<IdleRequestCallbackWrapper> { 26 : public RefCounted<IdleRequestCallbackWrapper> {
27 public: 27 public:
28 static PassRefPtr<IdleRequestCallbackWrapper> create( 28 static PassRefPtr<IdleRequestCallbackWrapper> create(
29 ScriptedIdleTaskController::CallbackId id, 29 ScriptedIdleTaskController::CallbackId id,
30 ScriptedIdleTaskController* controller) { 30 WTF::WeakPtr<ScriptedIdleTaskController> controller) {
31 return adoptRef(new IdleRequestCallbackWrapper(id, controller)); 31 return adoptRef(new IdleRequestCallbackWrapper(id, controller));
32 } 32 }
33 virtual ~IdleRequestCallbackWrapper() {} 33 virtual ~IdleRequestCallbackWrapper() {}
34 34
35 static void idleTaskFired( 35 static void idleTaskFired(
36 PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper, 36 PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper,
37 double deadlineSeconds) { 37 double deadlineSeconds) {
38 // TODO(rmcilroy): Implement clamping of deadline in some form. 38 // TODO(rmcilroy): Implement clamping of deadline in some form.
39 if (ScriptedIdleTaskController* controller = callbackWrapper->controller()) 39 if (ScriptedIdleTaskController* controller = callbackWrapper->controller())
40 controller->callbackFired(callbackWrapper->id(), deadlineSeconds, 40 controller->callbackFired(callbackWrapper->id(), deadlineSeconds,
41 IdleDeadline::CallbackType::CalledWhenIdle); 41 IdleDeadline::CallbackType::CalledWhenIdle);
42 callbackWrapper->cancel(); 42 callbackWrapper->cancel();
43 } 43 }
44 44
45 static void timeoutFired( 45 static void timeoutFired(
46 PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper) { 46 PassRefPtr<IdleRequestCallbackWrapper> callbackWrapper) {
47 if (ScriptedIdleTaskController* controller = callbackWrapper->controller()) 47 if (ScriptedIdleTaskController* controller = callbackWrapper->controller())
48 controller->callbackFired(callbackWrapper->id(), 48 controller->callbackFired(callbackWrapper->id(),
49 monotonicallyIncreasingTime(), 49 monotonicallyIncreasingTime(),
50 IdleDeadline::CallbackType::CalledByTimeout); 50 IdleDeadline::CallbackType::CalledByTimeout);
51 callbackWrapper->cancel(); 51 callbackWrapper->cancel();
52 } 52 }
53 53
54 void cancel() { m_controller = nullptr; } 54 void cancel() { m_controller = nullptr; }
55 55
56 ScriptedIdleTaskController::CallbackId id() const { return m_id; } 56 ScriptedIdleTaskController::CallbackId id() const { return m_id; }
57 ScriptedIdleTaskController* controller() const { return m_controller; } 57 ScriptedIdleTaskController* controller() const { return m_controller.get(); }
58 58
59 private: 59 private:
60 IdleRequestCallbackWrapper(ScriptedIdleTaskController::CallbackId id, 60 IdleRequestCallbackWrapper(
61 ScriptedIdleTaskController* controller) 61 ScriptedIdleTaskController::CallbackId id,
62 WTF::WeakPtr<ScriptedIdleTaskController> controller)
62 : m_id(id), m_controller(controller) {} 63 : m_id(id), m_controller(controller) {}
63 64
64 ScriptedIdleTaskController::CallbackId m_id; 65 ScriptedIdleTaskController::CallbackId m_id;
65 Persistent<ScriptedIdleTaskController> m_controller; 66 WTF::WeakPtr<ScriptedIdleTaskController> m_controller;
sof 2017/01/06 09:31:04 WeakPersistent<> is used to hold onto GC-managed o
Xiaocheng 2017/01/06 09:56:28 Done. Thanks!
66 }; 67 };
67 68
68 } // namespace internal 69 } // namespace internal
69 70
70 ScriptedIdleTaskController::ScriptedIdleTaskController( 71 ScriptedIdleTaskController::ScriptedIdleTaskController(
71 ExecutionContext* context) 72 ExecutionContext* context)
72 : SuspendableObject(context), 73 : SuspendableObject(context),
73 m_scheduler(Platform::current()->currentThread()->scheduler()), 74 m_scheduler(Platform::current()->currentThread()->scheduler()),
74 m_nextCallbackId(0), 75 m_nextCallbackId(0),
76 m_weakPtrFactory(this),
75 m_suspended(false) { 77 m_suspended(false) {
76 suspendIfNeeded(); 78 suspendIfNeeded();
77 } 79 }
78 80
79 ScriptedIdleTaskController::~ScriptedIdleTaskController() {} 81 ScriptedIdleTaskController::~ScriptedIdleTaskController() {}
80 82
81 DEFINE_TRACE(ScriptedIdleTaskController) { 83 DEFINE_TRACE(ScriptedIdleTaskController) {
82 visitor->trace(m_callbacks); 84 visitor->trace(m_callbacks);
83 SuspendableObject::trace(visitor); 85 SuspendableObject::trace(visitor);
84 } 86 }
(...skipping 12 matching lines...) Expand all
97 99
98 ScriptedIdleTaskController::CallbackId 100 ScriptedIdleTaskController::CallbackId
99 ScriptedIdleTaskController::registerCallback( 101 ScriptedIdleTaskController::registerCallback(
100 IdleRequestCallback* callback, 102 IdleRequestCallback* callback,
101 const IdleRequestOptions& options) { 103 const IdleRequestOptions& options) {
102 CallbackId id = nextCallbackId(); 104 CallbackId id = nextCallbackId();
103 m_callbacks.set(id, callback); 105 m_callbacks.set(id, callback);
104 long long timeoutMillis = options.timeout(); 106 long long timeoutMillis = options.timeout();
105 107
106 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = 108 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper =
107 internal::IdleRequestCallbackWrapper::create(id, this); 109 internal::IdleRequestCallbackWrapper::create(
110 id, m_weakPtrFactory.createWeakPtr());
108 m_scheduler->postIdleTask( 111 m_scheduler->postIdleTask(
109 BLINK_FROM_HERE, 112 BLINK_FROM_HERE,
110 WTF::bind(&internal::IdleRequestCallbackWrapper::idleTaskFired, 113 WTF::bind(&internal::IdleRequestCallbackWrapper::idleTaskFired,
111 callbackWrapper)); 114 callbackWrapper));
112 if (timeoutMillis > 0) 115 if (timeoutMillis > 0)
113 m_scheduler->timerTaskRunner()->postDelayedTask( 116 m_scheduler->timerTaskRunner()->postDelayedTask(
114 BLINK_FROM_HERE, 117 BLINK_FROM_HERE,
115 WTF::bind(&internal::IdleRequestCallbackWrapper::timeoutFired, 118 WTF::bind(&internal::IdleRequestCallbackWrapper::timeoutFired,
116 callbackWrapper), 119 callbackWrapper),
117 timeoutMillis); 120 timeoutMillis);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 std::max((monotonicallyIncreasingTime() - deadlineSeconds) * 1000, 0.0); 186 std::max((monotonicallyIncreasingTime() - deadlineSeconds) * 1000, 0.0);
184 187
185 DEFINE_STATIC_LOCAL( 188 DEFINE_STATIC_LOCAL(
186 CustomCountHistogram, idleCallbackOverrunHistogram, 189 CustomCountHistogram, idleCallbackOverrunHistogram,
187 ("WebCore.ScriptedIdleTaskController.IdleCallbackOverrun", 0, 10000, 50)); 190 ("WebCore.ScriptedIdleTaskController.IdleCallbackOverrun", 0, 10000, 50));
188 idleCallbackOverrunHistogram.count(overrunMillis); 191 idleCallbackOverrunHistogram.count(overrunMillis);
189 } 192 }
190 193
191 void ScriptedIdleTaskController::contextDestroyed() { 194 void ScriptedIdleTaskController::contextDestroyed() {
192 m_callbacks.clear(); 195 m_callbacks.clear();
196 m_weakPtrFactory.revokeAll();
193 } 197 }
194 198
195 void ScriptedIdleTaskController::suspend() { 199 void ScriptedIdleTaskController::suspend() {
196 m_suspended = true; 200 m_suspended = true;
197 } 201 }
198 202
199 void ScriptedIdleTaskController::resume() { 203 void ScriptedIdleTaskController::resume() {
200 DCHECK(m_suspended); 204 DCHECK(m_suspended);
201 m_suspended = false; 205 m_suspended = false;
202 206
203 // Run any pending timeouts. 207 // Run any pending timeouts.
204 Vector<CallbackId> pendingTimeouts; 208 Vector<CallbackId> pendingTimeouts;
205 m_pendingTimeouts.swap(pendingTimeouts); 209 m_pendingTimeouts.swap(pendingTimeouts);
206 for (auto& id : pendingTimeouts) 210 for (auto& id : pendingTimeouts)
207 runCallback(id, monotonicallyIncreasingTime(), 211 runCallback(id, monotonicallyIncreasingTime(),
208 IdleDeadline::CallbackType::CalledByTimeout); 212 IdleDeadline::CallbackType::CalledByTimeout);
209 213
210 // Repost idle tasks for any remaining callbacks. 214 // Repost idle tasks for any remaining callbacks.
211 for (auto& callback : m_callbacks) { 215 for (auto& callback : m_callbacks) {
212 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper = 216 RefPtr<internal::IdleRequestCallbackWrapper> callbackWrapper =
213 internal::IdleRequestCallbackWrapper::create(callback.key, this); 217 internal::IdleRequestCallbackWrapper::create(
218 callback.key, m_weakPtrFactory.createWeakPtr());
214 m_scheduler->postIdleTask( 219 m_scheduler->postIdleTask(
215 BLINK_FROM_HERE, 220 BLINK_FROM_HERE,
216 WTF::bind(&internal::IdleRequestCallbackWrapper::idleTaskFired, 221 WTF::bind(&internal::IdleRequestCallbackWrapper::idleTaskFired,
217 callbackWrapper)); 222 callbackWrapper));
218 } 223 }
219 } 224 }
220 225
221 } // namespace blink 226 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/ScriptedIdleTaskController.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698