mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
`UnMergeNowIfLastOne` is called during shell destruction. When there are other shells with threads unmerged and the current destroying shell with thread merged. `UnMergeNowIfLastOne` should unmerge the threads. This PR Make `UnMergeNowIfLastOne` not only unmerge if the current merger is the last merger, but also unmerge if the current merger is the last merger that is merged. Fixes https://github.com/flutter/flutter/issues/127168 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
147 lines
5.5 KiB
C++
147 lines
5.5 KiB
C++
// 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.
|
|
|
|
#ifndef FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_
|
|
#define FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_
|
|
|
|
#include <condition_variable>
|
|
#include <mutex>
|
|
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/memory/ref_counted.h"
|
|
#include "flutter/fml/message_loop_task_queues.h"
|
|
#include "flutter/fml/shared_thread_merger.h"
|
|
|
|
namespace fml {
|
|
|
|
class MessageLoopImpl;
|
|
|
|
enum class RasterThreadStatus {
|
|
kRemainsMerged,
|
|
kRemainsUnmerged,
|
|
kUnmergedNow
|
|
};
|
|
|
|
/// This class is a client and proxy between the rasterizer and
|
|
/// |SharedThreadMerger|. The multiple |RasterThreadMerger| instances with same
|
|
/// owner_queue_id and same subsumed_queue_id share the same
|
|
/// |SharedThreadMerger| instance. Whether they share the same inner instance is
|
|
/// determined by |RasterThreadMerger::CreateOrShareThreadMerger| method.
|
|
class RasterThreadMerger
|
|
: public fml::RefCountedThreadSafe<RasterThreadMerger> {
|
|
public:
|
|
// Merges the raster thread into platform thread for the duration of
|
|
// the lease term. Lease is managed by the caller by either calling
|
|
// |ExtendLeaseTo| or |DecrementLease|.
|
|
// When the caller merges with a lease term of say 2. The threads
|
|
// are going to remain merged until 2 invocations of |DecreaseLease|,
|
|
// unless an |ExtendLeaseTo| gets called.
|
|
//
|
|
// If the task queues are the same, we consider them statically merged.
|
|
// When task queues are statically merged this method becomes no-op.
|
|
void MergeWithLease(size_t lease_term);
|
|
|
|
// Gets the shared merger from current merger object
|
|
const fml::RefPtr<SharedThreadMerger>& GetSharedRasterThreadMerger() const;
|
|
|
|
/// Creates a new merger from parent, share the inside shared_merger member
|
|
/// when the platform_queue_id and raster_queue_id are same, otherwise create
|
|
/// a new shared_merger instance
|
|
static fml::RefPtr<fml::RasterThreadMerger> CreateOrShareThreadMerger(
|
|
const fml::RefPtr<fml::RasterThreadMerger>& parent_merger,
|
|
TaskQueueId platform_id,
|
|
TaskQueueId raster_id);
|
|
|
|
// 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.
|
|
//
|
|
// If the task queues are the same, we consider them statically merged.
|
|
// When task queues are statically merged, we never unmerge them and
|
|
// this method becomes no-op.
|
|
void UnMergeNowIfLastOne();
|
|
|
|
// If the task queues are the same, we consider them statically merged.
|
|
// When task queues are statically merged this method becomes no-op.
|
|
void ExtendLeaseTo(size_t lease_term);
|
|
|
|
// Returns |RasterThreadStatus::kUnmergedNow| if this call resulted in
|
|
// splitting the raster and platform threads. Reduces the lease term by 1.
|
|
//
|
|
// If the task queues are the same, we consider them statically merged.
|
|
// When task queues are statically merged this method becomes no-op.
|
|
RasterThreadStatus DecrementLease();
|
|
|
|
// The method is locked by current instance, and asks the shared instance of
|
|
// SharedThreadMerger and the merging state is determined by the
|
|
// lease_term_ counter.
|
|
bool IsMerged();
|
|
|
|
// Waits until the threads are merged.
|
|
//
|
|
// Must run on the platform task runner.
|
|
void WaitUntilMerged();
|
|
|
|
// Returns true if the current thread owns rasterizing.
|
|
// When the threads are merged, platform thread owns rasterizing.
|
|
// When un-merged, raster thread owns rasterizing.
|
|
bool IsOnRasterizingThread();
|
|
|
|
// Returns true if the current thread is the platform thread.
|
|
bool IsOnPlatformThread() const;
|
|
|
|
// Enables the thread merger.
|
|
void Enable();
|
|
|
|
// Disables the thread merger. Once disabled, any call to
|
|
// |MergeWithLease| or |UnMergeNowIfLastOne| results in a noop.
|
|
void Disable();
|
|
|
|
// Whether the thread merger is enabled. By default, the thread merger is
|
|
// enabled. If false, calls to |MergeWithLease| or |UnMergeNowIfLastOne|
|
|
// or |ExtendLeaseTo| or |DecrementLease| results in a noop.
|
|
bool IsEnabled();
|
|
|
|
// Registers a callback that can be used to clean up global state right after
|
|
// the thread configuration has changed.
|
|
//
|
|
// For example, it can be used to clear the GL context so it can be used in
|
|
// the next task from a different thread.
|
|
void SetMergeUnmergeCallback(const fml::closure& callback);
|
|
|
|
private:
|
|
fml::TaskQueueId platform_queue_id_;
|
|
fml::TaskQueueId gpu_queue_id_;
|
|
|
|
RasterThreadMerger(fml::TaskQueueId platform_queue_id,
|
|
fml::TaskQueueId gpu_queue_id);
|
|
RasterThreadMerger(fml::RefPtr<fml::SharedThreadMerger> shared_merger,
|
|
fml::TaskQueueId platform_queue_id,
|
|
fml::TaskQueueId gpu_queue_id);
|
|
|
|
const fml::RefPtr<fml::SharedThreadMerger> shared_merger_;
|
|
std::condition_variable merged_condition_;
|
|
std::mutex mutex_;
|
|
fml::closure merge_unmerge_callback_;
|
|
|
|
bool IsMergedUnSafe() const;
|
|
|
|
bool IsEnabledUnSafe() const;
|
|
|
|
// The platform_queue_id and gpu_queue_id are exactly the same.
|
|
// We consider the threads are always merged and cannot be unmerged.
|
|
bool TaskQueuesAreSame() const;
|
|
|
|
FML_FRIEND_REF_COUNTED_THREAD_SAFE(RasterThreadMerger);
|
|
FML_FRIEND_MAKE_REF_COUNTED(RasterThreadMerger);
|
|
FML_DISALLOW_COPY_AND_ASSIGN(RasterThreadMerger);
|
|
};
|
|
|
|
} // namespace fml
|
|
|
|
#endif // FML_SHELL_COMMON_TASK_RUNNER_MERGER_H_
|