Skip to content

Commit 94cd4b1

Browse files
knoppJonah Williamsloic-sharma
authored
[Embedder] Implement merged platform and UI thread (flutter#162944)
Fixes flutter#152337 Introduces `ui_task_runner` field on `FlutterCustomTaskRunners`. This lets the embedder to specify task runner for UI isolate tasks, allowing for merging platform and UI threads. With custom UI task runner there is no `MessageLoop` anymore for the UI thread, so the message loop task observer can no longer be used to flush microtask queue. Instead the microtask queue is flushed at the end of each `FlutterEngineRunTask` invocation if needed. This is handled internally by the embedder. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Jonah Williams <[email protected]> Co-authored-by: Loïc Sharma <[email protected]>
1 parent 7cd9e0f commit 94cd4b1

19 files changed

+310
-20
lines changed

engine/src/flutter/fml/message_loop_task_queues.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
namespace fml {
1818

1919
const size_t TaskQueueId::kUnmerged = ULONG_MAX;
20+
const size_t TaskQueueId::kInvalid = ULONG_MAX - 1;
2021

2122
namespace {
2223

engine/src/flutter/fml/task_queue_id.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@ class TaskQueueId {
1818
/// runner.
1919
static const size_t kUnmerged;
2020

21+
/// This constant indicates an invalid task queue. Used in embedder
22+
/// supplied task runners not associated with a task queue.
23+
static const size_t kInvalid;
24+
2125
/// Intializes a task queue with the given value as it's ID.
2226
explicit TaskQueueId(size_t value) : value_(value) {}
2327

2428
operator size_t() const { // NOLINT(google-explicit-constructor)
2529
return value_;
2630
}
2731

32+
bool is_valid() const { return value_ != kInvalid; }
33+
2834
private:
2935
size_t value_ = kUnmerged;
3036
};

engine/src/flutter/fml/task_runner.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner>,
5555

5656
/// Returns the unique identifier associated with the TaskRunner.
5757
/// \see fml::MessageLoopTaskQueues
58+
///
59+
/// Will be TaskQueueId::kInvalid for embedder supplied task runners
60+
/// that are not associated with a task queue.
5861
virtual TaskQueueId GetTaskQueueId();
5962

6063
/// Executes the \p task directly if the TaskRunner \p runner is the

engine/src/flutter/runtime/dart_isolate.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,13 @@ bool DartIsolate::Initialize(Dart_Isolate dart_isolate) {
510510
SetMessageHandlingTaskRunner(GetTaskRunners().GetPlatformTaskRunner(),
511511
true);
512512
} else {
513-
SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner(), false);
513+
// When running with custom UI task runner post directly to runner (there is
514+
// no task queue).
515+
bool post_directly_to_runner =
516+
GetTaskRunners().GetUITaskRunner() &&
517+
!GetTaskRunners().GetUITaskRunner()->GetTaskQueueId().is_valid();
518+
SetMessageHandlingTaskRunner(GetTaskRunners().GetUITaskRunner(),
519+
post_directly_to_runner);
514520
}
515521

516522
if (tonic::CheckAndHandleError(

engine/src/flutter/runtime/runtime_controller.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,12 @@ class RuntimeController : public PlatformConfigurationClient,
655655
return root_isolate_;
656656
}
657657

658+
void FlushMicrotaskQueue() {
659+
if (auto isolate = root_isolate_.lock()) {
660+
isolate->FlushMicrotasksNow();
661+
}
662+
}
663+
658664
std::shared_ptr<PlatformIsolateManager> GetPlatformIsolateManager() override {
659665
return platform_isolate_manager_;
660666
}

engine/src/flutter/shell/common/engine.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,4 +627,8 @@ void Engine::ShutdownPlatformIsolates() {
627627
runtime_controller_->ShutdownPlatformIsolates();
628628
}
629629

630+
void Engine::FlushMicrotaskQueue() {
631+
runtime_controller_->FlushMicrotaskQueue();
632+
}
633+
630634
} // namespace flutter

engine/src/flutter/shell/common/engine.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,11 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
978978
///
979979
void ShutdownPlatformIsolates();
980980

981+
//--------------------------------------------------------------------------
982+
/// @brief Flushes the microtask queue of the root isolate.
983+
///
984+
void FlushMicrotaskQueue();
985+
981986
private:
982987
// |RuntimeDelegate|
983988
std::string DefaultRouteName() override;

engine/src/flutter/shell/common/shell.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,12 @@ void Shell::NotifyLowMemoryWarning() const {
634634
// to purge them.
635635
}
636636

637+
void Shell::FlushMicrotaskQueue() const {
638+
if (engine_) {
639+
engine_->FlushMicrotaskQueue();
640+
}
641+
}
642+
637643
void Shell::RunEngine(RunConfiguration run_configuration) {
638644
RunEngine(std::move(run_configuration), nullptr);
639645
}

engine/src/flutter/shell/common/shell.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,13 @@ class Shell final : public PlatformView::Delegate,
289289
/// the rasterizer cache is purged.
290290
void NotifyLowMemoryWarning() const;
291291

292+
//----------------------------------------------------------------------------
293+
/// @brief Used by embedders to flush the microtask queue. Required
294+
/// when running with merged platform and UI threads, in which
295+
/// case the embedder is responsible for flushing the microtask
296+
/// queue.
297+
void FlushMicrotaskQueue() const;
298+
292299
//----------------------------------------------------------------------------
293300
/// @brief Used by embedders to check if all shell subcomponents are
294301
/// initialized. It is the embedder's responsibility to make this

engine/src/flutter/shell/common/vsync_waiter.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,16 @@ void VsyncWaiter::FireCallback(fml::TimePoint frame_start_time,
154154
void VsyncWaiter::PauseDartEventLoopTasks() {
155155
auto ui_task_queue_id = task_runners_.GetUITaskRunner()->GetTaskQueueId();
156156
auto task_queues = fml::MessageLoopTaskQueues::GetInstance();
157-
task_queues->PauseSecondarySource(ui_task_queue_id);
157+
if (ui_task_queue_id.is_valid()) {
158+
task_queues->PauseSecondarySource(ui_task_queue_id);
159+
}
158160
}
159161

160162
void VsyncWaiter::ResumeDartEventLoopTasks(fml::TaskQueueId ui_task_queue_id) {
161163
auto task_queues = fml::MessageLoopTaskQueues::GetInstance();
162-
task_queues->ResumeSecondarySource(ui_task_queue_id);
164+
if (ui_task_queue_id.is_valid()) {
165+
task_queues->ResumeSecondarySource(ui_task_queue_id);
166+
}
163167
}
164168

165169
} // namespace flutter

0 commit comments

Comments
 (0)