// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #define FML_USED_ON_EMBEDDER #include "flutter/fml/shared_thread_merger.h" #include #include namespace fml { SharedThreadMerger::SharedThreadMerger(fml::TaskQueueId owner, fml::TaskQueueId subsumed) : owner_(owner), subsumed_(subsumed), task_queues_(fml::MessageLoopTaskQueues::GetInstance()), enabled_(true) {} bool SharedThreadMerger::MergeWithLease(RasterThreadMergerId caller, size_t lease_term) { FML_DCHECK(lease_term > 0) << "lease_term should be positive."; std::scoped_lock lock(mutex_); if (IsMergedUnSafe()) { return true; } bool success = task_queues_->Merge(owner_, subsumed_); FML_CHECK(success) << "Unable to merge the raster and platform threads."; // Save the lease term lease_term_by_caller_[caller] = lease_term; return success; } bool SharedThreadMerger::UnMergeNowUnSafe() { FML_CHECK(IsAllLeaseTermsZeroUnSafe()) << "all lease term records must be zero before calling " "UnMergeNowUnSafe()"; bool success = task_queues_->Unmerge(owner_, subsumed_); FML_CHECK(success) << "Unable to un-merge the raster and platform threads."; return success; } bool SharedThreadMerger::UnMergeNowIfLastOne(RasterThreadMergerId caller) { std::scoped_lock lock(mutex_); lease_term_by_caller_.erase(caller); if (lease_term_by_caller_.empty() || IsAllLeaseTermsZeroUnSafe()) { return UnMergeNowUnSafe(); } return true; } bool SharedThreadMerger::DecrementLease(RasterThreadMergerId caller) { std::scoped_lock lock(mutex_); auto entry = lease_term_by_caller_.find(caller); bool exist = entry != lease_term_by_caller_.end(); if (exist) { std::atomic_size_t& lease_term_ref = entry->second; FML_CHECK(lease_term_ref > 0) << "lease_term should always be positive when merged, lease_term=" << lease_term_ref; lease_term_ref--; } else { FML_LOG(WARNING) << "The caller does not exist when calling " "DecrementLease(), ignored. This may happens after " "caller is erased in UnMergeNowIfLastOne(). caller=" << caller; } if (IsAllLeaseTermsZeroUnSafe()) { // Unmerge now because lease_term_ decreased to zero. UnMergeNowUnSafe(); return true; } return false; } void SharedThreadMerger::ExtendLeaseTo(RasterThreadMergerId caller, size_t lease_term) { FML_DCHECK(lease_term > 0) << "lease_term should be positive."; std::scoped_lock lock(mutex_); FML_DCHECK(IsMergedUnSafe()) << "should be merged state when calling this method"; lease_term_by_caller_[caller] = lease_term; } bool SharedThreadMerger::IsMergedUnSafe() const { return !IsAllLeaseTermsZeroUnSafe(); } bool SharedThreadMerger::IsEnabledUnSafe() const { return enabled_; } void SharedThreadMerger::SetEnabledUnSafe(bool enabled) { enabled_ = enabled; } bool SharedThreadMerger::IsAllLeaseTermsZeroUnSafe() const { return std::all_of(lease_term_by_caller_.begin(), lease_term_by_caller_.end(), [&](const auto& item) { return item.second == 0; }); } } // namespace fml