blob: 0b56b229d48344db1c34d8604eefb36813a0131b [file] [log] [blame]
// 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 <algorithm>
#include <set>
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