1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define FML_USED_ON_EMBEDDER
6
7#include "flutter/fml/shared_thread_merger.h"
8
9#include <algorithm>
10#include <set>
11
12namespace fml {
13
14SharedThreadMerger::SharedThreadMerger(fml::TaskQueueId owner,
15 fml::TaskQueueId subsumed)
16 : owner_(owner),
17 subsumed_(subsumed),
18 task_queues_(fml::MessageLoopTaskQueues::GetInstance()),
19 enabled_(true) {}
20
21bool SharedThreadMerger::MergeWithLease(RasterThreadMergerId caller,
22 size_t lease_term) {
23 FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
24 std::scoped_lock lock(mutex_);
25 if (IsMergedUnSafe()) {
26 return true;
27 }
28 bool success = task_queues_->Merge(owner: owner_, subsumed: subsumed_);
29 FML_CHECK(success) << "Unable to merge the raster and platform threads.";
30 // Save the lease term
31 lease_term_by_caller_[caller] = lease_term;
32 return success;
33}
34
35bool SharedThreadMerger::UnMergeNowUnSafe() {
36 FML_CHECK(IsAllLeaseTermsZeroUnSafe())
37 << "all lease term records must be zero before calling "
38 "UnMergeNowUnSafe()";
39 bool success = task_queues_->Unmerge(owner: owner_, subsumed: subsumed_);
40 FML_CHECK(success) << "Unable to un-merge the raster and platform threads.";
41 return success;
42}
43
44bool SharedThreadMerger::UnMergeNowIfLastOne(RasterThreadMergerId caller) {
45 std::scoped_lock lock(mutex_);
46 lease_term_by_caller_.erase(k: caller);
47 if (lease_term_by_caller_.empty() || IsAllLeaseTermsZeroUnSafe()) {
48 return UnMergeNowUnSafe();
49 }
50 return true;
51}
52
53bool SharedThreadMerger::DecrementLease(RasterThreadMergerId caller) {
54 std::scoped_lock lock(mutex_);
55 auto entry = lease_term_by_caller_.find(k: caller);
56 bool exist = entry != lease_term_by_caller_.end();
57 if (exist) {
58 std::atomic_size_t& lease_term_ref = entry->second;
59 FML_CHECK(lease_term_ref > 0)
60 << "lease_term should always be positive when merged, lease_term="
61 << lease_term_ref;
62 lease_term_ref--;
63 } else {
64 FML_LOG(WARNING) << "The caller does not exist when calling "
65 "DecrementLease(), ignored. This may happens after "
66 "caller is erased in UnMergeNowIfLastOne(). caller="
67 << caller;
68 }
69 if (IsAllLeaseTermsZeroUnSafe()) {
70 // Unmerge now because lease_term_ decreased to zero.
71 UnMergeNowUnSafe();
72 return true;
73 }
74 return false;
75}
76
77void SharedThreadMerger::ExtendLeaseTo(RasterThreadMergerId caller,
78 size_t lease_term) {
79 FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
80 std::scoped_lock lock(mutex_);
81 FML_DCHECK(IsMergedUnSafe())
82 << "should be merged state when calling this method";
83 lease_term_by_caller_[caller] = lease_term;
84}
85
86bool SharedThreadMerger::IsMergedUnSafe() const {
87 return !IsAllLeaseTermsZeroUnSafe();
88}
89
90bool SharedThreadMerger::IsEnabledUnSafe() const {
91 return enabled_;
92}
93
94void SharedThreadMerger::SetEnabledUnSafe(bool enabled) {
95 enabled_ = enabled;
96}
97
98bool SharedThreadMerger::IsAllLeaseTermsZeroUnSafe() const {
99 return std::all_of(first: lease_term_by_caller_.begin(), last: lease_term_by_caller_.end(),
100 pred: [&](const auto& item) { return item.second == 0; });
101}
102
103} // namespace fml
104

source code of flutter_engine/flutter/fml/shared_thread_merger.cc