| 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..61b4f455802da021a16bb97614efc61db01fa3e2 100644
|
| --- a/third_party/WebKit/Source/platform/WebTaskRunner.cpp
|
| +++ b/third_party/WebKit/Source/platform/WebTaskRunner.cpp
|
| @@ -6,6 +6,66 @@
|
|
|
| namespace blink {
|
|
|
| +// This class holds a reference to a TaskHandle to keep it alive while a task is
|
| +// pending in a task queue, and clears the reference on the task disposal, so
|
| +// that it doesn't leave a circular reference like below:
|
| +// 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.
|
| +// CancelOnTaskDestruction is needed to break the circle by clearing |m_task|
|
| +// when the wrapped WTF::Closure is deleted.
|
| +class TaskHandle::CancelOnTaskDestruction {
|
| + public:
|
| + explicit CancelOnTaskDestruction(RefPtr<TaskHandle> handle)
|
| + : m_handle(std::move(handle)) {}
|
| +
|
| + CancelOnTaskDestruction(CancelOnTaskDestruction&&) = default;
|
| +
|
| + void cancel() const {
|
| + if (m_handle)
|
| + m_handle->cancel();
|
| + }
|
| +
|
| + ~CancelOnTaskDestruction() { cancel(); }
|
| +
|
| + private:
|
| + RefPtr<TaskHandle> m_handle;
|
| + DISALLOW_COPY_AND_ASSIGN(CancelOnTaskDestruction);
|
| +};
|
| +
|
| +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 CancelOnTaskDestruction& 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 +94,27 @@ 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::CancelOnTaskDestruction(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::CancelOnTaskDestruction(handle)),
|
| + delayMs);
|
| + return handle;
|
| +}
|
| +
|
| } // namespace blink
|
|
|