-
Notifications
You must be signed in to change notification settings - Fork 6k
Ensure threads are merged when tearing down the Rasterizer #19919
Changes from all commits
f31e62f
54c8447
a9214c2
55f758d
c197572
edd4dfd
11e014c
2b8f977
cdbee3d
292a647
9863985
0c6e1c3
b4a37cb
566d3da
b104fcd
72049f3
bbb0210
5d60a2e
5471a38
f0aa0a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,58 +17,97 @@ RasterThreadMerger::RasterThreadMerger(fml::TaskQueueId platform_queue_id, | |
| gpu_queue_id_(gpu_queue_id), | ||
| task_queues_(fml::MessageLoopTaskQueues::GetInstance()), | ||
| lease_term_(kLeaseNotSet) { | ||
| is_merged_ = task_queues_->Owns(platform_queue_id_, gpu_queue_id_); | ||
| FML_CHECK(!task_queues_->Owns(platform_queue_id_, gpu_queue_id_)); | ||
| } | ||
|
|
||
| void RasterThreadMerger::MergeWithLease(size_t lease_term) { | ||
| if (TaskQueuesAreSame()) { | ||
| return; | ||
| } | ||
|
|
||
| FML_DCHECK(lease_term > 0) << "lease_term should be positive."; | ||
| if (!is_merged_) { | ||
| is_merged_ = task_queues_->Merge(platform_queue_id_, gpu_queue_id_); | ||
| std::scoped_lock lock(lease_term_mutex_); | ||
| if (!IsMergedUnSafe()) { | ||
| bool success = task_queues_->Merge(platform_queue_id_, gpu_queue_id_); | ||
| FML_CHECK(success) << "Unable to merge the raster and platform threads."; | ||
| lease_term_ = lease_term; | ||
| } | ||
| merged_condition_.notify_one(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. grab lock. |
||
| } | ||
|
|
||
| void RasterThreadMerger::UnMergeNow() { | ||
| if (TaskQueuesAreSame()) { | ||
| return; | ||
| } | ||
|
|
||
| std::scoped_lock lock(lease_term_mutex_); | ||
| lease_term_ = 0; | ||
| bool success = task_queues_->Unmerge(platform_queue_id_); | ||
| FML_CHECK(success) << "Unable to un-merge the raster and platform threads."; | ||
| } | ||
|
|
||
| bool RasterThreadMerger::IsOnPlatformThread() const { | ||
| return MessageLoop::GetCurrentTaskQueueId() == platform_queue_id_; | ||
| } | ||
|
|
||
| bool RasterThreadMerger::IsOnRasterizingThread() const { | ||
| if (is_merged_) { | ||
| bool RasterThreadMerger::IsOnRasterizingThread() { | ||
| if (IsMergedUnSafe()) { | ||
| return IsOnPlatformThread(); | ||
| } else { | ||
| return !IsOnPlatformThread(); | ||
| } | ||
| } | ||
|
|
||
| void RasterThreadMerger::ExtendLeaseTo(size_t lease_term) { | ||
| FML_DCHECK(lease_term > 0) << "lease_term should be positive."; | ||
| if (TaskQueuesAreSame()) { | ||
| return; | ||
| } | ||
| std::scoped_lock lock(lease_term_mutex_); | ||
| FML_DCHECK(IsMergedUnSafe()) << "lease_term should be positive."; | ||
| if (lease_term_ != kLeaseNotSet && | ||
| static_cast<int>(lease_term) > lease_term_) { | ||
| lease_term_ = lease_term; | ||
| } | ||
| } | ||
|
|
||
| bool RasterThreadMerger::IsMerged() const { | ||
| return is_merged_; | ||
| bool RasterThreadMerger::IsMerged() { | ||
| std::scoped_lock lock(lease_term_mutex_); | ||
| return IsMergedUnSafe(); | ||
| } | ||
|
|
||
| RasterThreadStatus RasterThreadMerger::DecrementLease() { | ||
| if (!is_merged_) { | ||
| return RasterThreadStatus::kRemainsUnmerged; | ||
| bool RasterThreadMerger::IsMergedUnSafe() { | ||
| return lease_term_ > 0 || TaskQueuesAreSame(); | ||
| } | ||
|
|
||
| bool RasterThreadMerger::TaskQueuesAreSame() { | ||
| return platform_queue_id_ == gpu_queue_id_; | ||
| } | ||
|
|
||
| void RasterThreadMerger::WaitUntilMerged() { | ||
| if (TaskQueuesAreSame()) { | ||
| return; | ||
| } | ||
| FML_CHECK(IsOnPlatformThread()); | ||
| std::unique_lock<std::mutex> lock(lease_term_mutex_); | ||
| merged_condition_.wait(lock, [&] { return IsMergedUnSafe(); }); | ||
| } | ||
|
|
||
| // we haven't been set to merge. | ||
| if (lease_term_ == kLeaseNotSet) { | ||
| RasterThreadStatus RasterThreadMerger::DecrementLease() { | ||
| if (TaskQueuesAreSame()) { | ||
| return RasterThreadStatus::kRemainsMerged; | ||
| } | ||
| std::unique_lock<std::mutex> lock(lease_term_mutex_); | ||
| if (!IsMergedUnSafe()) { | ||
| return RasterThreadStatus::kRemainsUnmerged; | ||
| } | ||
|
|
||
| FML_DCHECK(lease_term_ > 0) | ||
| << "lease_term should always be positive when merged."; | ||
| lease_term_--; | ||
| if (lease_term_ == 0) { | ||
| bool success = task_queues_->Unmerge(platform_queue_id_); | ||
| FML_CHECK(success) << "Unable to un-merge the raster and platform threads."; | ||
| is_merged_ = false; | ||
| // |UnMergeNow| is going to acquire the lock again. | ||
| lock.unlock(); | ||
| UnMergeNow(); | ||
| return RasterThreadStatus::kUnmergedNow; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -208,3 +208,96 @@ TEST(RasterThreadMerger, LeaseExtension) { | |
| thread1.join(); | ||
| thread2.join(); | ||
| } | ||
|
|
||
| TEST(RasterThreadMerger, WaitUntilMerged) { | ||
| fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger; | ||
|
|
||
| fml::AutoResetWaitableEvent create_thread_merger_latch; | ||
| fml::MessageLoop* loop_platform = nullptr; | ||
| fml::AutoResetWaitableEvent latch_platform; | ||
| fml::AutoResetWaitableEvent term_platform; | ||
| fml::AutoResetWaitableEvent latch_merged; | ||
| std::thread thread_platform([&]() { | ||
| fml::MessageLoop::EnsureInitializedForCurrentThread(); | ||
| loop_platform = &fml::MessageLoop::GetCurrent(); | ||
| latch_platform.Signal(); | ||
| create_thread_merger_latch.Wait(); | ||
| raster_thread_merger->WaitUntilMerged(); | ||
| latch_merged.Signal(); | ||
| term_platform.Wait(); | ||
| }); | ||
|
|
||
| const int kNumFramesMerged = 5; | ||
| fml::MessageLoop* loop_raster = nullptr; | ||
| fml::AutoResetWaitableEvent term_raster; | ||
| std::thread thread_raster([&]() { | ||
| fml::MessageLoop::EnsureInitializedForCurrentThread(); | ||
| loop_raster = &fml::MessageLoop::GetCurrent(); | ||
| latch_platform.Wait(); | ||
| fml::TaskQueueId qid_platform = | ||
| loop_platform->GetTaskRunner()->GetTaskQueueId(); | ||
| fml::TaskQueueId qid_raster = | ||
| loop_raster->GetTaskRunner()->GetTaskQueueId(); | ||
| raster_thread_merger = | ||
| fml::MakeRefCounted<fml::RasterThreadMerger>(qid_platform, qid_raster); | ||
| ASSERT_FALSE(raster_thread_merger->IsMerged()); | ||
| create_thread_merger_latch.Signal(); | ||
| raster_thread_merger->MergeWithLease(kNumFramesMerged); | ||
| term_raster.Wait(); | ||
| }); | ||
|
|
||
| latch_merged.Wait(); | ||
| ASSERT_TRUE(raster_thread_merger->IsMerged()); | ||
|
|
||
| for (int i = 0; i < kNumFramesMerged; i++) { | ||
| ASSERT_TRUE(raster_thread_merger->IsMerged()); | ||
| raster_thread_merger->DecrementLease(); | ||
| } | ||
|
|
||
| ASSERT_FALSE(raster_thread_merger->IsMerged()); | ||
|
|
||
| term_platform.Signal(); | ||
| term_raster.Signal(); | ||
| thread_platform.join(); | ||
| thread_raster.join(); | ||
| } | ||
|
|
||
| TEST(RasterThreadMerger, HandleTaskQueuesAreTheSame) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: missing checks for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should make |
||
| fml::MessageLoop* loop1 = nullptr; | ||
| fml::AutoResetWaitableEvent latch1; | ||
| fml::AutoResetWaitableEvent term1; | ||
| std::thread thread1([&loop1, &latch1, &term1]() { | ||
| fml::MessageLoop::EnsureInitializedForCurrentThread(); | ||
| loop1 = &fml::MessageLoop::GetCurrent(); | ||
| latch1.Signal(); | ||
| term1.Wait(); | ||
| }); | ||
|
|
||
| latch1.Wait(); | ||
|
|
||
| fml::TaskQueueId qid1 = loop1->GetTaskRunner()->GetTaskQueueId(); | ||
| fml::TaskQueueId qid2 = qid1; | ||
| const auto raster_thread_merger_ = | ||
| fml::MakeRefCounted<fml::RasterThreadMerger>(qid1, qid2); | ||
| // Statically merged. | ||
| ASSERT_TRUE(raster_thread_merger_->IsMerged()); | ||
|
|
||
| // Test decrement lease and unmerge are both no-ops. | ||
| // The task queues should be always merged. | ||
| const int kNumFramesMerged = 5; | ||
| raster_thread_merger_->MergeWithLease(kNumFramesMerged); | ||
|
|
||
| for (int i = 0; i < kNumFramesMerged; i++) { | ||
| ASSERT_TRUE(raster_thread_merger_->IsMerged()); | ||
| raster_thread_merger_->DecrementLease(); | ||
| } | ||
|
|
||
| ASSERT_TRUE(raster_thread_merger_->IsMerged()); | ||
|
|
||
| // Wait until merged should also return immediately. | ||
| raster_thread_merger_->WaitUntilMerged(); | ||
| ASSERT_TRUE(raster_thread_merger_->IsMerged()); | ||
|
|
||
| term1.Signal(); | ||
| thread1.join(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -77,6 +77,10 @@ void Rasterizer::Teardown() { | |
| compositor_context_->OnGrContextDestroyed(); | ||
| surface_.reset(); | ||
| last_layer_tree_.reset(); | ||
| if (raster_thread_merger_.get() != nullptr && | ||
| raster_thread_merger_.get()->IsMerged()) { | ||
| raster_thread_merger_->UnMergeNow(); | ||
| } | ||
| } | ||
|
|
||
| void Rasterizer::NotifyLowMemoryWarning() const { | ||
|
|
@@ -659,6 +663,24 @@ std::optional<size_t> Rasterizer::GetResourceCacheMaxBytes() const { | |
| return std::nullopt; | ||
| } | ||
|
|
||
| bool Rasterizer::EnsureThreadsAreMerged() { | ||
| if (surface_ == nullptr || raster_thread_merger_.get() == nullptr) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in what case There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the rasterizer has already been torn down, the |
||
| return false; | ||
| } | ||
| fml::TaskRunner::RunNowOrPostTask( | ||
| delegate_.GetTaskRunners().GetRasterTaskRunner(), | ||
| [weak_this = weak_factory_.GetWeakPtr(), | ||
| thread_merger = raster_thread_merger_]() { | ||
| if (weak_this->surface_ == nullptr) { | ||
| return; | ||
| } | ||
| thread_merger->MergeWithLease(10); | ||
| }); | ||
| raster_thread_merger_->WaitUntilMerged(); | ||
| FML_DCHECK(raster_thread_merger_->IsMerged()); | ||
| return true; | ||
cyanglaz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| Rasterizer::Screenshot::Screenshot() {} | ||
|
|
||
| Rasterizer::Screenshot::Screenshot(sk_sp<SkData> p_data, SkISize p_size) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Would you mind adding a TODO, and filing an issue about reverting this logic once Android is fixed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We actually might not need to revert this as I think this make sense. waiting for @iskakaushik to confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, this is good.