diff --git a/fml/raster_thread_merger.h b/fml/raster_thread_merger.h index 3ad4a4e27da0c..2fd0bc22e3ab5 100644 --- a/fml/raster_thread_merger.h +++ b/fml/raster_thread_merger.h @@ -53,10 +53,10 @@ class RasterThreadMerger TaskQueueId platform_id, TaskQueueId raster_id); - // Un-merges the threads now if current caller is the last merge caller, - // and it resets the lease term to 0, otherwise it will remove the caller - // record and return. The multiple caller records were recorded after - // |MergeWithLease| or |ExtendLeaseTo| method. + // Un-merges the threads now if current caller is the last merged caller, + // and it resets the lease term to 0, otherwise it will remove + // the caller record and return. The multiple caller records were recorded + // after |MergeWithLease| or |ExtendLeaseTo| method. // // Must be executed on the raster task runner. // diff --git a/fml/raster_thread_merger_unittests.cc b/fml/raster_thread_merger_unittests.cc index 43beb63947e1f..b4b9621d23196 100644 --- a/fml/raster_thread_merger_unittests.cc +++ b/fml/raster_thread_merger_unittests.cc @@ -594,6 +594,42 @@ TEST(RasterThreadMerger, TheLastCallerOfMultipleMergersCanUnmergeNow) { ASSERT_FALSE(raster_thread_merger2->IsMerged()); } +TEST(RasterThreadMerger, TheLastMergedCallerOfMultipleMergersCanUnmergeNow) { + TaskQueueWrapper queue1; + TaskQueueWrapper queue2; + fml::TaskQueueId qid1 = queue1.GetTaskQueueId(); + fml::TaskQueueId qid2 = queue2.GetTaskQueueId(); + // Two mergers will share one same inner merger + const auto raster_thread_merger1 = + fml::RasterThreadMerger::CreateOrShareThreadMerger(nullptr, qid1, qid2); + + const size_t kNumFramesMerged = 1; + ASSERT_FALSE(raster_thread_merger1->IsMerged()); + + // Merge using the mergers + raster_thread_merger1->MergeWithLease(kNumFramesMerged); + ASSERT_TRUE(raster_thread_merger1->IsMerged()); + + for (size_t i = 0; i < kNumFramesMerged; i++) { + // Un-merge thread merger 1. + raster_thread_merger1->DecrementLease(); + } + ASSERT_FALSE(raster_thread_merger1->IsMerged()); + + const auto raster_thread_merger2 = + fml::RasterThreadMerger::CreateOrShareThreadMerger(raster_thread_merger1, + qid1, qid2); + ASSERT_FALSE(raster_thread_merger2->IsMerged()); + raster_thread_merger2->MergeWithLease(kNumFramesMerged); + ASSERT_TRUE(raster_thread_merger2->IsMerged()); + + // One caller state becomes no callers left. + raster_thread_merger2->UnMergeNowIfLastOne(); + // Check if unmerged + ASSERT_FALSE(raster_thread_merger1->IsMerged()); + ASSERT_FALSE(raster_thread_merger2->IsMerged()); +} + /// This case tests multiple standalone engines using independent merger to /// merge two different raster threads into the same platform thread. TEST(RasterThreadMerger, diff --git a/fml/shared_thread_merger.cc b/fml/shared_thread_merger.cc index 15fac3e2fa0c2..0b56b229d4834 100644 --- a/fml/shared_thread_merger.cc +++ b/fml/shared_thread_merger.cc @@ -44,10 +44,10 @@ bool SharedThreadMerger::UnMergeNowUnSafe() { bool SharedThreadMerger::UnMergeNowIfLastOne(RasterThreadMergerId caller) { std::scoped_lock lock(mutex_); lease_term_by_caller_.erase(caller); - if (!lease_term_by_caller_.empty()) { - return true; + if (lease_term_by_caller_.empty() || IsAllLeaseTermsZeroUnSafe()) { + return UnMergeNowUnSafe(); } - return UnMergeNowUnSafe(); + return true; } bool SharedThreadMerger::DecrementLease(RasterThreadMergerId caller) {