Index: third_party/WebKit/Source/platform/WebTaskRunner.cpp |
diff --git a/third_party/WebKit/Source/platform/WebTaskRunner.cpp b/third_party/WebKit/Source/platform/WebTaskRunner.cpp |
index 548dbc9ac1d500a31170856fbe2966d1ce612059..3f2c0d1b5eee72317a5d6311ad33c168b5453b4e 100644 |
--- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp |
+++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp |
@@ -6,6 +6,65 @@ |
namespace blink { |
+// This class holds a reference to a TaskHandle to make sure it keeps alive |
dcheng
2016/10/21 06:14:46
Nit: to make sure it keeps alive => to keep it ali
tzik
2016/10/25 07:03:52
Done.
|
+// while a task is pending in a task queue, and clears its reference to avoid a |
dcheng
2016/10/21 06:14:46
Nit: until we read line 22-23, it's not clear when
|
+// possible circular references in a case below: |
haraken
2016/10/20 17:07:37
avoid a circular reference like below
tzik
2016/10/25 07:03:52
Done.
|
+// struct Foo : GarbageCollected<Foo> { |
+// void bar() {} |
+// RefPtr<TaskHandle> m_handle; |
+// }; |
+// |
+// foo->m_handle = taskRunner->postCancellableTask( |
+// BLINK_FROM_HERE, WTF::bind(&Foo::bar, wrapPersistent(foo))); |
+// |
+// There is a circular reference in the example above as: |
+// foo -> m_handle -> m_task -> Persistent<Foo> in WTF::bind. |
+// CancelOnScopeOut is needed to cut the circle by clearing |m_task| when the |
dcheng
2016/10/21 06:14:46
Nit: cut the circle => break the cycle
tzik
2016/10/25 07:03:52
Done.
|
+// wrapped WTF::Closure is deleted. |
+class TaskHandle::CancelOnScopeOut { |
haraken
2016/10/20 17:07:37
I'd rename this to CancelOnTaskDestruction
tzik
2016/10/25 07:03:52
Done.
|
+ public: |
+ explicit CancelOnScopeOut(WTF::PassRefPtr<TaskHandle> handle) |
dcheng
2016/10/21 06:14:46
Nit: RefPtr here (also no WTF:: prefix is needed)
tzik
2016/10/25 07:03:52
Done.
|
+ : m_handle(std::move(handle)) {} |
+ |
+ CancelOnScopeOut(CancelOnScopeOut&&) = default; |
+ |
+ void cancel() const { |
+ if (m_handle) |
dcheng
2016/10/21 06:14:46
Is there a time when this will be null?
tzik
2016/10/25 07:03:52
Yes. We make a temporary object on WTF::bind call
|
+ m_handle->cancel(); |
+ } |
+ |
+ ~CancelOnScopeOut() { cancel(); } |
+ |
+ private: |
+ RefPtr<TaskHandle> m_handle; |
+}; |
+ |
+bool TaskHandle::isActive() const { |
+ return static_cast<bool>(m_task); |
+} |
+ |
+void TaskHandle::cancel() { |
+ std::unique_ptr<WTF::Closure> task = std::move(m_task); |
+ m_weakPtrFactory.revokeAll(); |
+} |
+ |
+TaskHandle::~TaskHandle() {} |
+ |
+TaskHandle::TaskHandle(std::unique_ptr<WTF::Closure> task) |
+ : m_task(std::move(task)), m_weakPtrFactory(this) { |
+ DCHECK(m_task); |
+} |
+ |
+void TaskHandle::run(const CancelOnScopeOut& scoper) { |
+ std::unique_ptr<WTF::Closure> task = std::move(m_task); |
+ cancel(); |
+ (*task)(); |
+} |
+ |
+WTF::WeakPtr<TaskHandle> TaskHandle::asWeakPtr() { |
+ return m_weakPtrFactory.createWeakPtr(); |
+} |
+ |
void WebTaskRunner::postTask(const WebTraceLocation& location, |
std::unique_ptr<CrossThreadClosure> task) { |
toSingleThreadTaskRunner()->PostTask(location, |
@@ -34,4 +93,26 @@ void WebTaskRunner::postDelayedTask(const WebTraceLocation& location, |
base::TimeDelta::FromMilliseconds(delayMs)); |
} |
+RefPtr<TaskHandle> WebTaskRunner::postCancellableTask( |
+ const WebTraceLocation& location, |
+ std::unique_ptr<WTF::Closure> task) { |
+ DCHECK(runsTasksOnCurrentThread()); |
+ RefPtr<TaskHandle> handle = adoptRef(new TaskHandle(std::move(task))); |
+ postTask(location, WTF::bind(&TaskHandle::run, handle->asWeakPtr(), |
+ TaskHandle::CancelOnScopeOut(handle))); |
+ return handle; |
+} |
+ |
+RefPtr<TaskHandle> WebTaskRunner::postDelayedCancellableTask( |
+ const WebTraceLocation& location, |
+ std::unique_ptr<WTF::Closure> task, |
+ long long delayMs) { |
+ DCHECK(runsTasksOnCurrentThread()); |
+ RefPtr<TaskHandle> handle = adoptRef(new TaskHandle(std::move(task))); |
+ postDelayedTask(location, WTF::bind(&TaskHandle::run, handle->asWeakPtr(), |
+ TaskHandle::CancelOnScopeOut(handle)), |
+ delayMs); |
+ return handle; |
+} |
+ |
} // namespace blink |