Commit c5c01f7e authored by Stephen McGruer's avatar Stephen McGruer Committed by Commit Bot

[AnimationWorklet] Properly setup and teardown the backing thread

This CL adds refcounting around the backing thread for AnimationWorklet,
such that the backing thread is actually torn down when all
AnimationWorkletThread objects are destroyed.

Bug: 892527
Change-Id: I750b63c74146a4a4dc7b3b1ebda0e66b269b13dc
Reviewed-on: https://chromium-review.googlesource.com/c/1286772Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Reviewed-by: default avatarYi Gu <yigu@chromium.org>
Commit-Queue: Stephen McGruer <smcgruer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600842}
parent 2ce2c70e
......@@ -36,7 +36,6 @@ bool AnimationWorklet::NeedsToCreateGlobalScope() {
WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() {
DCHECK(NeedsToCreateGlobalScope());
AnimationWorkletThread::EnsureSharedBackingThread();
Document* document = To<Document>(GetExecutionContext());
AnimationWorkletProxyClient* proxy_client =
......
......@@ -57,7 +57,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
AnimationWorkletGlobalScopeTest() = default;
void SetUp() override {
AnimationWorkletThread::EnsureSharedBackingThread();
PageTestBase::SetUp(IntSize());
Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/"));
......@@ -65,10 +64,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
}
void TearDown() override {
AnimationWorkletThread::ClearSharedBackingThread();
}
std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread(
AnimationWorkletProxyClient* proxy_client) {
std::unique_ptr<AnimationWorkletThread> thread =
......
......@@ -15,6 +15,10 @@
namespace blink {
namespace {
unsigned s_ref_count = 0;
}
std::unique_ptr<AnimationWorkletThread> AnimationWorkletThread::Create(
WorkerReportingProxy& worker_reporting_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
......@@ -27,9 +31,19 @@ template class WorkletThreadHolder<AnimationWorkletThread>;
AnimationWorkletThread::AnimationWorkletThread(
WorkerReportingProxy& worker_reporting_proxy)
: WorkerThread(worker_reporting_proxy) {}
: WorkerThread(worker_reporting_proxy) {
DCHECK(IsMainThread());
if (++s_ref_count == 1) {
EnsureSharedBackingThread();
}
}
AnimationWorkletThread::~AnimationWorkletThread() = default;
AnimationWorkletThread::~AnimationWorkletThread() {
DCHECK(IsMainThread());
if (--s_ref_count == 0) {
ClearSharedBackingThread();
}
}
WorkerBackingThread& AnimationWorkletThread::GetWorkerBackingThread() {
return *WorkletThreadHolder<AnimationWorkletThread>::GetInstance()
......@@ -53,20 +67,29 @@ void AnimationWorkletThread::CollectAllGarbage() {
done_event.Wait();
}
WorkerOrWorkletGlobalScope* AnimationWorkletThread::CreateWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
"AnimationWorkletThread::CreateWorkerGlobalScope");
return AnimationWorkletGlobalScope::Create(std::move(creation_params), this);
}
void AnimationWorkletThread::EnsureSharedBackingThread() {
DCHECK(IsMainThread());
WorkletThreadHolder<AnimationWorkletThread>::EnsureInstance(
ThreadCreationParams(WebThreadType::kAnimationWorkletThread));
}
void AnimationWorkletThread::ClearSharedBackingThread() {
DCHECK(IsMainThread());
DCHECK_EQ(s_ref_count, 0u);
WorkletThreadHolder<AnimationWorkletThread>::ClearInstance();
}
WorkerOrWorkletGlobalScope* AnimationWorkletThread::CreateWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
"AnimationWorkletThread::CreateWorkerGlobalScope");
return AnimationWorkletGlobalScope::Create(std::move(creation_params), this);
// static
WorkletThreadHolder<AnimationWorkletThread>*
AnimationWorkletThread::GetWorkletThreadHolderForTesting() {
return WorkletThreadHolder<AnimationWorkletThread>::GetInstance();
}
} // namespace blink
......@@ -7,6 +7,7 @@
#include <memory>
#include "third_party/blink/renderer/core/workers/worker_thread.h"
#include "third_party/blink/renderer/core/workers/worklet_thread_holder.h"
#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
......@@ -29,8 +30,8 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread {
// This may block the main thread.
static void CollectAllGarbage();
static void EnsureSharedBackingThread();
static void ClearSharedBackingThread();
static WorkletThreadHolder<AnimationWorkletThread>*
GetWorkletThreadHolderForTesting();
private:
explicit AnimationWorkletThread(WorkerReportingProxy&);
......@@ -43,6 +44,9 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread {
WebThreadType GetThreadType() const override {
return WebThreadType::kAnimationWorkletThread;
}
void EnsureSharedBackingThread();
void ClearSharedBackingThread();
};
} // namespace blink
......
......@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "third_party/blink/renderer/core/workers/worklet_thread_holder.h"
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
......@@ -48,7 +49,6 @@ class TestAnimationWorkletProxyClient : public AnimationWorkletProxyClient {
class AnimationWorkletThreadTest : public PageTestBase {
public:
void SetUp() override {
AnimationWorkletThread::EnsureSharedBackingThread();
PageTestBase::SetUp(IntSize());
Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/"));
......@@ -56,10 +56,6 @@ class AnimationWorkletThreadTest : public PageTestBase {
reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
}
void TearDown() override {
AnimationWorkletThread::ClearSharedBackingThread();
}
std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread() {
WorkerClients* clients = WorkerClients::Create();
ProvideAnimationWorkletProxyClientTo(clients,
......@@ -161,8 +157,8 @@ TEST_F(AnimationWorkletThreadTest, CreateSecondAndTerminateFirst) {
second_worklet->WaitForShutdownForTesting();
}
// Tests that a new WebThread is created if all existing worklets are
// terminated before a new worklet is created.
// Tests that the WebThread is reused if all existing worklets are terminated
// before a new worklet is created, as long as the worklets are not destructed.
TEST_F(AnimationWorkletThreadTest, TerminateFirstAndCreateSecond) {
// Create the first worklet, wait until it is initialized, and terminate it.
std::unique_ptr<AnimationWorkletThread> worklet =
......@@ -216,4 +212,42 @@ TEST_F(AnimationWorkletThreadTest, CreatingSecondDuringTerminationOfFirst) {
second_worklet->WaitForShutdownForTesting();
}
// Tests that the backing thread is correctly created, torn down, and recreated
// as AnimationWorkletThreads are created and destroyed.
TEST_F(AnimationWorkletThreadTest, WorkletThreadHolderIsRefCountedProperly) {
EXPECT_FALSE(AnimationWorkletThread::GetWorkletThreadHolderForTesting());
std::unique_ptr<AnimationWorkletThread> worklet =
CreateAnimationWorkletThread();
ASSERT_TRUE(worklet.get());
WorkletThreadHolder<AnimationWorkletThread>* holder =
AnimationWorkletThread::GetWorkletThreadHolderForTesting();
EXPECT_TRUE(holder);
std::unique_ptr<AnimationWorkletThread> worklet2 =
CreateAnimationWorkletThread();
ASSERT_TRUE(worklet2.get());
WorkletThreadHolder<AnimationWorkletThread>* holder2 =
AnimationWorkletThread::GetWorkletThreadHolderForTesting();
EXPECT_EQ(holder, holder2);
worklet->Terminate();
worklet->WaitForShutdownForTesting();
worklet.reset();
EXPECT_TRUE(AnimationWorkletThread::GetWorkletThreadHolderForTesting());
worklet2->Terminate();
worklet2->WaitForShutdownForTesting();
worklet2.reset();
EXPECT_FALSE(AnimationWorkletThread::GetWorkletThreadHolderForTesting());
std::unique_ptr<AnimationWorkletThread> worklet3 =
CreateAnimationWorkletThread();
ASSERT_TRUE(worklet3.get());
EXPECT_TRUE(AnimationWorkletThread::GetWorkletThreadHolderForTesting());
worklet3->Terminate();
worklet3->WaitForShutdownForTesting();
}
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment