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() { ...@@ -36,7 +36,6 @@ bool AnimationWorklet::NeedsToCreateGlobalScope() {
WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() { WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() {
DCHECK(NeedsToCreateGlobalScope()); DCHECK(NeedsToCreateGlobalScope());
AnimationWorkletThread::EnsureSharedBackingThread();
Document* document = To<Document>(GetExecutionContext()); Document* document = To<Document>(GetExecutionContext());
AnimationWorkletProxyClient* proxy_client = AnimationWorkletProxyClient* proxy_client =
......
...@@ -57,7 +57,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase { ...@@ -57,7 +57,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
AnimationWorkletGlobalScopeTest() = default; AnimationWorkletGlobalScopeTest() = default;
void SetUp() override { void SetUp() override {
AnimationWorkletThread::EnsureSharedBackingThread();
PageTestBase::SetUp(IntSize()); PageTestBase::SetUp(IntSize());
Document* document = &GetDocument(); Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/")); document->SetURL(KURL("https://example.com/"));
...@@ -65,10 +64,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase { ...@@ -65,10 +64,6 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
reporting_proxy_ = std::make_unique<WorkerReportingProxy>(); reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
} }
void TearDown() override {
AnimationWorkletThread::ClearSharedBackingThread();
}
std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread( std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread(
AnimationWorkletProxyClient* proxy_client) { AnimationWorkletProxyClient* proxy_client) {
std::unique_ptr<AnimationWorkletThread> thread = std::unique_ptr<AnimationWorkletThread> thread =
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
namespace blink { namespace blink {
namespace {
unsigned s_ref_count = 0;
}
std::unique_ptr<AnimationWorkletThread> AnimationWorkletThread::Create( std::unique_ptr<AnimationWorkletThread> AnimationWorkletThread::Create(
WorkerReportingProxy& worker_reporting_proxy) { WorkerReportingProxy& worker_reporting_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"), TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"),
...@@ -27,9 +31,19 @@ template class WorkletThreadHolder<AnimationWorkletThread>; ...@@ -27,9 +31,19 @@ template class WorkletThreadHolder<AnimationWorkletThread>;
AnimationWorkletThread::AnimationWorkletThread( AnimationWorkletThread::AnimationWorkletThread(
WorkerReportingProxy& worker_reporting_proxy) 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() { WorkerBackingThread& AnimationWorkletThread::GetWorkerBackingThread() {
return *WorkletThreadHolder<AnimationWorkletThread>::GetInstance() return *WorkletThreadHolder<AnimationWorkletThread>::GetInstance()
...@@ -53,20 +67,29 @@ void AnimationWorkletThread::CollectAllGarbage() { ...@@ -53,20 +67,29 @@ void AnimationWorkletThread::CollectAllGarbage() {
done_event.Wait(); 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() { void AnimationWorkletThread::EnsureSharedBackingThread() {
DCHECK(IsMainThread());
WorkletThreadHolder<AnimationWorkletThread>::EnsureInstance( WorkletThreadHolder<AnimationWorkletThread>::EnsureInstance(
ThreadCreationParams(WebThreadType::kAnimationWorkletThread)); ThreadCreationParams(WebThreadType::kAnimationWorkletThread));
} }
void AnimationWorkletThread::ClearSharedBackingThread() { void AnimationWorkletThread::ClearSharedBackingThread() {
DCHECK(IsMainThread());
DCHECK_EQ(s_ref_count, 0u);
WorkletThreadHolder<AnimationWorkletThread>::ClearInstance(); WorkletThreadHolder<AnimationWorkletThread>::ClearInstance();
} }
WorkerOrWorkletGlobalScope* AnimationWorkletThread::CreateWorkerGlobalScope( // static
std::unique_ptr<GlobalScopeCreationParams> creation_params) { WorkletThreadHolder<AnimationWorkletThread>*
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("animation-worklet"), AnimationWorkletThread::GetWorkletThreadHolderForTesting() {
"AnimationWorkletThread::CreateWorkerGlobalScope"); return WorkletThreadHolder<AnimationWorkletThread>::GetInstance();
return AnimationWorkletGlobalScope::Create(std::move(creation_params), this);
} }
} // namespace blink } // namespace blink
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "third_party/blink/renderer/core/workers/worker_thread.h" #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" #include "third_party/blink/renderer/modules/modules_export.h"
namespace blink { namespace blink {
...@@ -29,8 +30,8 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread { ...@@ -29,8 +30,8 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread {
// This may block the main thread. // This may block the main thread.
static void CollectAllGarbage(); static void CollectAllGarbage();
static void EnsureSharedBackingThread(); static WorkletThreadHolder<AnimationWorkletThread>*
static void ClearSharedBackingThread(); GetWorkletThreadHolderForTesting();
private: private:
explicit AnimationWorkletThread(WorkerReportingProxy&); explicit AnimationWorkletThread(WorkerReportingProxy&);
...@@ -43,6 +44,9 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread { ...@@ -43,6 +44,9 @@ class MODULES_EXPORT AnimationWorkletThread final : public WorkerThread {
WebThreadType GetThreadType() const override { WebThreadType GetThreadType() const override {
return WebThreadType::kAnimationWorkletThread; return WebThreadType::kAnimationWorkletThread;
} }
void EnsureSharedBackingThread();
void ClearSharedBackingThread();
}; };
} // namespace blink } // namespace blink
......
...@@ -24,6 +24,7 @@ ...@@ -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_or_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.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_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/modules/animationworklet/animation_worklet_proxy_client.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h" #include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
...@@ -48,7 +49,6 @@ class TestAnimationWorkletProxyClient : public AnimationWorkletProxyClient { ...@@ -48,7 +49,6 @@ class TestAnimationWorkletProxyClient : public AnimationWorkletProxyClient {
class AnimationWorkletThreadTest : public PageTestBase { class AnimationWorkletThreadTest : public PageTestBase {
public: public:
void SetUp() override { void SetUp() override {
AnimationWorkletThread::EnsureSharedBackingThread();
PageTestBase::SetUp(IntSize()); PageTestBase::SetUp(IntSize());
Document* document = &GetDocument(); Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/")); document->SetURL(KURL("https://example.com/"));
...@@ -56,10 +56,6 @@ class AnimationWorkletThreadTest : public PageTestBase { ...@@ -56,10 +56,6 @@ class AnimationWorkletThreadTest : public PageTestBase {
reporting_proxy_ = std::make_unique<WorkerReportingProxy>(); reporting_proxy_ = std::make_unique<WorkerReportingProxy>();
} }
void TearDown() override {
AnimationWorkletThread::ClearSharedBackingThread();
}
std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread() { std::unique_ptr<AnimationWorkletThread> CreateAnimationWorkletThread() {
WorkerClients* clients = WorkerClients::Create(); WorkerClients* clients = WorkerClients::Create();
ProvideAnimationWorkletProxyClientTo(clients, ProvideAnimationWorkletProxyClientTo(clients,
...@@ -161,8 +157,8 @@ TEST_F(AnimationWorkletThreadTest, CreateSecondAndTerminateFirst) { ...@@ -161,8 +157,8 @@ TEST_F(AnimationWorkletThreadTest, CreateSecondAndTerminateFirst) {
second_worklet->WaitForShutdownForTesting(); second_worklet->WaitForShutdownForTesting();
} }
// Tests that a new WebThread is created if all existing worklets are // Tests that the WebThread is reused if all existing worklets are terminated
// terminated before a new worklet is created. // before a new worklet is created, as long as the worklets are not destructed.
TEST_F(AnimationWorkletThreadTest, TerminateFirstAndCreateSecond) { TEST_F(AnimationWorkletThreadTest, TerminateFirstAndCreateSecond) {
// Create the first worklet, wait until it is initialized, and terminate it. // Create the first worklet, wait until it is initialized, and terminate it.
std::unique_ptr<AnimationWorkletThread> worklet = std::unique_ptr<AnimationWorkletThread> worklet =
...@@ -216,4 +212,42 @@ TEST_F(AnimationWorkletThreadTest, CreatingSecondDuringTerminationOfFirst) { ...@@ -216,4 +212,42 @@ TEST_F(AnimationWorkletThreadTest, CreatingSecondDuringTerminationOfFirst) {
second_worklet->WaitForShutdownForTesting(); 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 } // 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