From c3b2a3f30602e5de6a6be785fecd4a4814ac826e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E7=84=B6?= Date: Fri, 14 Jun 2019 12:57:24 +0800 Subject: [PATCH 1/2] boost shell startup --- shell/common/shell.cc | 571 ++++++++++-------- shell/common/shell.h | 43 +- .../platform/android/android_shell_holder.cc | 24 +- shell/platform/embedder/embedder_engine.cc | 52 +- 4 files changed, 379 insertions(+), 311 deletions(-) diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 2127e7f38bef1..830d88ff034a6 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -36,11 +36,8 @@ namespace flutter { constexpr char kSkiaChannel[] = "flutter/skia"; std::unique_ptr Shell::CreateShellOnPlatformThread( - DartVMRef vm, TaskRunners task_runners, Settings settings, - fml::RefPtr isolate_snapshot, - fml::RefPtr shared_snapshot, Shell::CreateCallback on_create_platform_view, Shell::CreateCallback on_create_rasterizer) { if (!task_runners.IsValid()) { @@ -48,8 +45,7 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( return nullptr; } - auto shell = - std::unique_ptr(new Shell(std::move(vm), task_runners, settings)); + auto shell = std::unique_ptr(new Shell(task_runners, settings)); // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*shell.get()); @@ -64,63 +60,48 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( return nullptr; } - // Create the IO manager on the IO thread. The IO manager must be initialized - // first because it has state that the other subsystems depend on. It must - // first be booted and the necessary references obtained to initialize the - // other subsystems. - fml::AutoResetWaitableEvent io_latch; - std::unique_ptr io_manager; + shell->platform_view_ = std::move(platform_view); + shell->platform_view_promise_.set_value(shell->platform_view_->GetWeakPtr()); + + // Create the IO manager on the IO thread. auto io_task_runner = shell->GetTaskRunners().GetIOTaskRunner(); fml::TaskRunner::RunNowOrPostTask( io_task_runner, - [&io_latch, // - &io_manager, // - &platform_view, // - io_task_runner // + [shell = shell.get(), // + io_task_runner // ]() { TRACE_EVENT0("flutter", "ShellSetupIOSubsystem"); - io_manager = std::make_unique( - platform_view->CreateResourceContext(), io_task_runner); - io_latch.Signal(); + auto io_manager = std::make_unique( + shell->GetPlatformView()->CreateResourceContext(), io_task_runner); + shell->io_manager_ = std::move(io_manager); + shell->io_manager_promise_.set_value(shell->io_manager_->GetWeakPtr()); }); - io_latch.Wait(); // Create the rasterizer on the GPU thread. - fml::AutoResetWaitableEvent gpu_latch; - std::unique_ptr rasterizer; - fml::WeakPtr snapshot_delegate; fml::TaskRunner::RunNowOrPostTask( - task_runners.GetGPUTaskRunner(), [&gpu_latch, // - &rasterizer, // - on_create_rasterizer, // - shell = shell.get(), // - &snapshot_delegate // + task_runners.GetGPUTaskRunner(), [on_create_rasterizer, // + shell = shell.get() // ]() { TRACE_EVENT0("flutter", "ShellSetupGPUSubsystem"); if (auto new_rasterizer = on_create_rasterizer(*shell)) { - rasterizer = std::move(new_rasterizer); - snapshot_delegate = rasterizer->GetSnapshotDelegate(); + shell->rasterizer_ = std::move(new_rasterizer); + shell->rasterizer_promise_.set_value( + shell->rasterizer_->GetWeakPtr()); } - gpu_latch.Signal(); }); - gpu_latch.Wait(); - // Create the engine on the UI thread. - fml::AutoResetWaitableEvent ui_latch; - std::unique_ptr engine; fml::TaskRunner::RunNowOrPostTask( shell->GetTaskRunners().GetUITaskRunner(), - fml::MakeCopyable([&ui_latch, // - &engine, // - shell = shell.get(), // - isolate_snapshot = std::move(isolate_snapshot), // - shared_snapshot = std::move(shared_snapshot), // - vsync_waiter = std::move(vsync_waiter), // - snapshot_delegate = std::move(snapshot_delegate), // - io_manager = io_manager->GetWeakPtr() // + fml::MakeCopyable([shell = shell.get(), // + vsync_waiter = std::move(vsync_waiter) // ]() mutable { TRACE_EVENT0("flutter", "ShellSetupUISubsystem"); + + auto vm = DartVMRef::Create(shell->settings_); + FML_CHECK(vm) << "Must be able to initialize the VM."; + shell->vm_ = vm.get(); + const auto& task_runners = shell->GetTaskRunners(); // The animator is owned by the UI thread but it gets its vsync pulses @@ -128,28 +109,24 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( auto animator = std::make_unique(*shell, task_runners, std::move(vsync_waiter)); - engine = std::make_unique(*shell, // - *shell->GetDartVM(), // - std::move(isolate_snapshot), // - std::move(shared_snapshot), // - task_runners, // - shell->GetSettings(), // - std::move(animator), // - std::move(snapshot_delegate), // - std::move(io_manager) // + auto engine = std::make_unique( + *shell, // + *&vm, // + vm->GetVMData()->GetIsolateSnapshot(), // + DartSnapshot::Empty(), // + task_runners, // + shell->GetSettings(), // + std::move(animator), // + shell->GetRasterizer()->GetSnapshotDelegate(), // + shell->GetIOManager() // ); - ui_latch.Signal(); + shell->engine_ = std::move(engine); + shell->engine_promise_.set_value(shell->engine_->GetWeakPtr()); + vm->GetServiceProtocol()->AddHandler( + shell, shell->GetServiceProtocolDescription()); })); - ui_latch.Wait(); - // We are already on the platform thread. So there is no platform latch to - // wait on. - - if (!shell->Setup(std::move(platform_view), // - std::move(engine), // - std::move(rasterizer), // - std::move(io_manager)) // - ) { + if (!shell->Setup()) { return nullptr; } @@ -214,33 +191,6 @@ std::unique_ptr Shell::Create( TRACE_EVENT0("flutter", "Shell::Create"); - auto vm = DartVMRef::Create(settings); - FML_CHECK(vm) << "Must be able to initialize the VM."; - - auto vm_data = vm->GetVMData(); - - return Shell::Create(std::move(task_runners), // - std::move(settings), // - vm_data->GetIsolateSnapshot(), // isolate snapshot - DartSnapshot::Empty(), // shared snapshot - std::move(on_create_platform_view), // - std::move(on_create_rasterizer), // - std::move(vm) // - ); -} - -std::unique_ptr Shell::Create( - TaskRunners task_runners, - Settings settings, - fml::RefPtr isolate_snapshot, - fml::RefPtr shared_snapshot, - Shell::CreateCallback on_create_platform_view, - Shell::CreateCallback on_create_rasterizer, - DartVMRef vm) { - PerformInitializationTasks(settings); - - TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots"); - if (!task_runners.IsValid() || !on_create_platform_view || !on_create_rasterizer) { return nullptr; @@ -250,23 +200,17 @@ std::unique_ptr Shell::Create( std::unique_ptr shell; fml::TaskRunner::RunNowOrPostTask( task_runners.GetPlatformTaskRunner(), - fml::MakeCopyable([&latch, // - vm = std::move(vm), // - &shell, // - task_runners = std::move(task_runners), // - settings, // - isolate_snapshot = std::move(isolate_snapshot), // - shared_snapshot = std::move(shared_snapshot), // - on_create_platform_view, // - on_create_rasterizer // + fml::MakeCopyable([&latch, // + &shell, // + task_runners = std::move(task_runners), // + settings, // + on_create_platform_view, // + on_create_rasterizer // ]() mutable { - shell = CreateShellOnPlatformThread(std::move(vm), - std::move(task_runners), // - settings, // - std::move(isolate_snapshot), // - std::move(shared_snapshot), // - on_create_platform_view, // - on_create_rasterizer // + shell = CreateShellOnPlatformThread(std::move(task_runners), // + settings, // + on_create_platform_view, // + on_create_rasterizer // ); latch.Signal(); })); @@ -274,12 +218,18 @@ std::unique_ptr Shell::Create( return shell; } -Shell::Shell(DartVMRef vm, TaskRunners task_runners, Settings settings) +Shell::Shell(TaskRunners task_runners, Settings settings) : task_runners_(std::move(task_runners)), settings_(std::move(settings)), - vm_(std::move(vm)), + platform_view_future_(std::shared_future>( + platform_view_promise_.get_future())), + engine_future_(std::shared_future>( + engine_promise_.get_future())), + rasterizer_future_(std::shared_future>( + rasterizer_promise_.get_future())), + io_manager_future_(std::shared_future>( + io_manager_promise_.get_future())), weak_factory_(this) { - FML_CHECK(vm_) << "Must have access to VM to create a shell."; FML_DCHECK(task_runners_.IsValid()); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); @@ -321,33 +271,34 @@ Shell::~Shell() { PersistentCache::GetCacheForProcess()->RemoveWorkerTaskRunner( task_runners_.GetIOTaskRunner()); - vm_->GetServiceProtocol()->RemoveHandler(this); - fml::AutoResetWaitableEvent ui_latch, gpu_latch, platform_latch, io_latch; fml::TaskRunner::RunNowOrPostTask( task_runners_.GetUITaskRunner(), - fml::MakeCopyable([engine = std::move(engine_), &ui_latch]() mutable { - engine.reset(); + fml::MakeCopyable([shell = GetShell(), &ui_latch]() mutable { + shell->vm_->GetServiceProtocol()->RemoveHandler(shell.get()); + shell->engine_future_.wait(); + shell->engine_.reset(); ui_latch.Signal(); })); ui_latch.Wait(); fml::TaskRunner::RunNowOrPostTask( task_runners_.GetGPUTaskRunner(), - fml::MakeCopyable( - [rasterizer = std::move(rasterizer_), &gpu_latch]() mutable { - rasterizer.reset(); - gpu_latch.Signal(); - })); + fml::MakeCopyable([shell = GetShell(), &gpu_latch]() mutable { + shell->rasterizer_future_.wait(); + shell->rasterizer_.reset(); + gpu_latch.Signal(); + })); gpu_latch.Wait(); fml::TaskRunner::RunNowOrPostTask( task_runners_.GetIOTaskRunner(), - fml::MakeCopyable([io_manager = std::move(io_manager_), - platform_view = platform_view_.get(), - &io_latch]() mutable { - io_manager.reset(); + fml::MakeCopyable([shell = GetShell(), &io_latch]() mutable { + shell->platform_view_future_.wait(); + shell->io_manager_future_.wait(); + shell->io_manager_.reset(); + auto platform_view = shell->platform_view_.get(); if (platform_view) { platform_view->ReleaseResourceContext(); } @@ -361,9 +312,8 @@ Shell::~Shell() { // example, the NSOpenGLContext on the Mac. fml::TaskRunner::RunNowOrPostTask( task_runners_.GetPlatformTaskRunner(), - fml::MakeCopyable([platform_view = std::move(platform_view_), - &platform_latch]() mutable { - platform_view.reset(); + fml::MakeCopyable([shell = GetShell(), &platform_latch]() mutable { + shell->platform_view_.reset(); platform_latch.Signal(); })); platform_latch.Wait(); @@ -373,34 +323,13 @@ bool Shell::IsSetup() const { return is_setup_; } -bool Shell::Setup(std::unique_ptr platform_view, - std::unique_ptr engine, - std::unique_ptr rasterizer, - std::unique_ptr io_manager) { +bool Shell::Setup() { if (is_setup_) { return false; } - if (!platform_view || !engine || !rasterizer || !io_manager) { - return false; - } - - platform_view_ = std::move(platform_view); - engine_ = std::move(engine); - rasterizer_ = std::move(rasterizer); - io_manager_ = std::move(io_manager); - - // The weak ptr must be generated in the platform thread which owns the unique - // ptr. - // - // TODO(liyuqian): make weak_rasterizer_ and weak_platform_view_ and use - // them in the getters. - weak_engine_ = engine_->GetWeakPtr(); - is_setup_ = true; - vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription()); - PersistentCache::GetCacheForProcess()->AddWorkerTaskRunner( task_runners_.GetIOTaskRunner()); @@ -418,23 +347,48 @@ const TaskRunners& Shell::GetTaskRunners() const { return task_runners_; } -fml::WeakPtr Shell::GetRasterizer() { - FML_DCHECK(is_setup_); - return rasterizer_->GetWeakPtr(); +fml::WeakPtr Shell::GetIOManager() const { + if (io_manager_) { + return io_manager_->GetWeakPtr(); + } + if (io_manager_future_.valid()) { + return io_manager_future_.get(); + } + return {}; } -fml::WeakPtr Shell::GetEngine() { - FML_DCHECK(is_setup_); - return weak_engine_; +fml::WeakPtr Shell::GetRasterizer() const { + if (rasterizer_) { + return rasterizer_->GetWeakPtr(); + } + if (rasterizer_future_.valid()) { + return rasterizer_future_.get(); + } + return {}; } -fml::WeakPtr Shell::GetPlatformView() { - FML_DCHECK(is_setup_); - return platform_view_->GetWeakPtr(); +fml::WeakPtr Shell::GetEngine() const { + if (engine_) { + return engine_->GetWeakPtr(); + } + if (engine_future_.valid()) { + return engine_future_.get(); + } + return {}; +} + +fml::WeakPtr Shell::GetPlatformView() const { + if (platform_view_) { + return platform_view_->GetWeakPtr(); + } + if (platform_view_future_.valid()) { + return platform_view_future_.get(); + } + return {}; } -DartVM* Shell::GetDartVM() { - return &vm_; +fml::WeakPtr Shell::GetShell() const { + return weak_factory_.GetWeakPtr(); } // |PlatformView::Delegate| @@ -448,17 +402,36 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { // setup/suspension of all activities that may be interacting with the GPU in // a synchronous fashion. - fml::AutoResetWaitableEvent latch; - auto gpu_task = fml::MakeCopyable([rasterizer = rasterizer_->GetWeakPtr(), // - surface = std::move(surface), // - &latch]() mutable { - if (rasterizer) { - rasterizer->Setup(std::move(surface)); + auto ui_task = [shell = GetShell()] { + if (shell) { + auto engine = shell->GetEngine(); + if (engine) { + engine->OnOutputSurfaceCreated(); + } } - // Step 3: All done. Signal the latch that the platform thread is waiting - // on. - latch.Signal(); - }); + }; + + fml::AutoResetWaitableEvent latch; + auto gpu_task = + fml::MakeCopyable([shell = GetShell(), // + surface = std::move(surface), // + ui_task_runner = task_runners_.GetUITaskRunner(), // + ui_task, &latch]() mutable { + if (shell) { + auto rasterizer = shell->GetRasterizer(); + if (rasterizer) { + rasterizer->Setup(std::move(surface)); + } + } + + // Step 2: Next, post a task on the UI thread to tell the engine that it + // has an output surface. + fml::TaskRunner::RunNowOrPostTask(ui_task_runner, ui_task); + + // Step 3: All done. No need to wait for ui task. + // Signal the latch that the platform thread is waiting on. + latch.Signal(); + }); // The normal flow executed by this method is that the platform thread is // starting the sequence and waiting on the latch. Later the UI thread posts @@ -472,15 +445,26 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { bool should_post_gpu_task = task_runners_.GetGPUTaskRunner() != task_runners_.GetPlatformTaskRunner(); - auto ui_task = [engine = engine_->GetWeakPtr(), // - gpu_task_runner = task_runners_.GetGPUTaskRunner(), // - gpu_task, should_post_gpu_task, - &latch // - ] { - if (engine) { - engine->OnOutputSurfaceCreated(); + // Threading: Capture platform view by raw pointer and not the weak pointer. + // We are going to use the pointer on the IO thread which is not safe with a + // weak pointer. However, we are preventing the platform view from being + // collected by using a latch. + auto* platform_view = GetPlatformView().get(); + + FML_DCHECK(platform_view); + + auto io_task = [shell = GetShell(), platform_view, + gpu_task_runner = task_runners_.GetGPUTaskRunner(), gpu_task, + &latch, should_post_gpu_task] { + if (shell) { + auto io_manager = shell->GetIOManager(); + if (io_manager && !io_manager->GetResourceContext()) { + io_manager->NotifyResourceContextAvailable( + platform_view->CreateResourceContext()); + } } - // Step 2: Next, tell the GPU thread that it should create a surface for its + + // Step 1: Tell the GPU thread that it should create a surface for its // rasterizer. if (should_post_gpu_task) { fml::TaskRunner::RunNowOrPostTask(gpu_task_runner, gpu_task); @@ -491,25 +475,6 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { } }; - // Threading: Capture platform view by raw pointer and not the weak pointer. - // We are going to use the pointer on the IO thread which is not safe with a - // weak pointer. However, we are preventing the platform view from being - // collected by using a latch. - auto* platform_view = platform_view_.get(); - - FML_DCHECK(platform_view); - - auto io_task = [io_manager = io_manager_->GetWeakPtr(), platform_view, - ui_task_runner = task_runners_.GetUITaskRunner(), ui_task] { - if (io_manager && !io_manager->GetResourceContext()) { - io_manager->NotifyResourceContextAvailable( - platform_view->CreateResourceContext()); - } - // Step 1: Next, post a task on the UI thread to tell the engine that it has - // an output surface. - fml::TaskRunner::RunNowOrPostTask(ui_task_runner, ui_task); - }; - fml::TaskRunner::RunNowOrPostTask(task_runners_.GetIOTaskRunner(), io_task); latch.Wait(); @@ -534,16 +499,18 @@ void Shell::OnPlatformViewDestroyed() { fml::AutoResetWaitableEvent latch; - auto io_task = [io_manager = io_manager_.get(), &latch]() { - // Execute any pending Skia object deletions while GPU access is still - // allowed. - io_manager->GetSkiaUnrefQueue()->Drain(); + auto io_task = [io_manager = GetIOManager(), &latch]() { + if (io_manager) { + // Execute any pending Skia object deletions while GPU access is still + // allowed. + io_manager->GetSkiaUnrefQueue()->Drain(); + } // Step 3: All done. Signal the latch that the platform thread is waiting // on. latch.Signal(); }; - auto gpu_task = [rasterizer = rasterizer_->GetWeakPtr(), + auto gpu_task = [rasterizer = GetRasterizer(), io_task_runner = task_runners_.GetIOTaskRunner(), io_task]() { if (rasterizer) { @@ -565,7 +532,7 @@ void Shell::OnPlatformViewDestroyed() { bool should_post_gpu_task = task_runners_.GetGPUTaskRunner() != task_runners_.GetPlatformTaskRunner(); - auto ui_task = [engine = engine_->GetWeakPtr(), + auto ui_task = [engine = GetEngine(), gpu_task_runner = task_runners_.GetGPUTaskRunner(), gpu_task, should_post_gpu_task, &latch]() { if (engine) { @@ -600,12 +567,15 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask( - [engine = engine_->GetWeakPtr(), metrics]() { - if (engine) { - engine->SetViewportMetrics(metrics); - } - }); + task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), metrics]() { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->SetViewportMetrics(metrics); + } + }); } // |PlatformView::Delegate| @@ -615,7 +585,11 @@ void Shell::OnPlatformViewDispatchPlatformMessage( FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetUITaskRunner()->PostTask( - [engine = engine_->GetWeakPtr(), message = std::move(message)] { + [shell = GetShell(), message = std::move(message)] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchPlatformMessage(std::move(message)); } @@ -629,9 +603,13 @@ void Shell::OnPlatformViewDispatchPointerDataPacket( TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_); FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable( - [engine = engine_->GetWeakPtr(), packet = std::move(packet), - flow_id = next_pointer_flow_id_] { + task_runners_.GetUITaskRunner()->PostTask( + fml::MakeCopyable([shell = GetShell(), packet = std::move(packet), + flow_id = next_pointer_flow_id_] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchPointerDataPacket(*packet, flow_id); } @@ -647,7 +625,11 @@ void Shell::OnPlatformViewDispatchSemanticsAction(int32_t id, FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetUITaskRunner()->PostTask( - [engine = engine_->GetWeakPtr(), id, action, args = std::move(args)] { + [shell = GetShell(), id, action, args = std::move(args)] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchSemanticsAction(id, action, std::move(args)); } @@ -659,12 +641,15 @@ void Shell::OnPlatformViewSetSemanticsEnabled(bool enabled) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask( - [engine = engine_->GetWeakPtr(), enabled] { - if (engine) { - engine->SetSemanticsEnabled(enabled); - } - }); + task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), enabled] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->SetSemanticsEnabled(enabled); + } + }); } // |PlatformView::Delegate| @@ -672,12 +657,15 @@ void Shell::OnPlatformViewSetAccessibilityFeatures(int32_t flags) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask( - [engine = engine_->GetWeakPtr(), flags] { - if (engine) { - engine->SetAccessibilityFeatures(flags); - } - }); + task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), flags] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->SetAccessibilityFeatures(flags); + } + }); } // |PlatformView::Delegate| @@ -686,14 +674,17 @@ void Shell::OnPlatformViewRegisterTexture( FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), texture] { - if (rasterizer) { - if (auto* registry = rasterizer->GetTextureRegistry()) { - registry->RegisterTexture(texture); - } - } - }); + task_runners_.GetGPUTaskRunner()->PostTask([shell = GetShell(), texture] { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); + if (rasterizer) { + if (auto* registry = rasterizer->GetTextureRegistry()) { + registry->RegisterTexture(texture); + } + } + }); } // |PlatformView::Delegate| @@ -702,7 +693,11 @@ void Shell::OnPlatformViewUnregisterTexture(int64_t texture_id) { FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() { + [shell = GetShell(), texture_id]() { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); if (rasterizer) { if (auto* registry = rasterizer->GetTextureRegistry()) { registry->UnregisterTexture(texture_id); @@ -718,7 +713,15 @@ void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) { // Tell the rasterizer that one of its textures has a new frame available. task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), texture_id]() { + [shell = GetShell(), texture_id]() { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); + if (!rasterizer) { + return; + } + auto* registry = rasterizer->GetTextureRegistry(); if (!registry) { @@ -735,7 +738,11 @@ void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) { }); // Schedule a new frame without having to rebuild the layer tree. - task_runners_.GetUITaskRunner()->PostTask([engine = engine_->GetWeakPtr()]() { + task_runners_.GetUITaskRunner()->PostTask([shell = GetShell()]() { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->ScheduleFrame(false); } @@ -748,7 +755,11 @@ void Shell::OnPlatformViewSetNextFrameCallback(fml::closure closure) { FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), closure = std::move(closure)]() { + [shell = GetShell(), closure = std::move(closure)]() { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); if (rasterizer) { rasterizer->SetNextFrameCallback(std::move(closure)); } @@ -760,8 +771,9 @@ void Shell::OnAnimatorBeginFrame(fml::TimePoint frame_time) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); - if (engine_) { - engine_->BeginFrame(frame_time); + auto engine = GetEngine(); + if (engine) { + engine->BeginFrame(frame_time); } } @@ -770,8 +782,9 @@ void Shell::OnAnimatorNotifyIdle(int64_t deadline) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); - if (engine_) { - engine_->NotifyIdle(deadline); + auto engine = GetEngine(); + if (engine) { + engine->NotifyIdle(deadline); } } @@ -780,8 +793,11 @@ void Shell::OnAnimatorDraw(fml::RefPtr> pipeline) { FML_DCHECK(is_setup_); task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), - pipeline = std::move(pipeline)]() { + [shell = GetShell(), pipeline = std::move(pipeline)]() { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); if (rasterizer) { rasterizer->Draw(pipeline); } @@ -792,12 +808,15 @@ void Shell::OnAnimatorDraw(fml::RefPtr> pipeline) { void Shell::OnAnimatorDrawLastLayerTree() { FML_DCHECK(is_setup_); - task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr()]() { - if (rasterizer) { - rasterizer->DrawLastLayerTree(); - } - }); + task_runners_.GetGPUTaskRunner()->PostTask([shell = GetShell()]() { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); + if (rasterizer) { + rasterizer->DrawLastLayerTree(); + } + }); } // |Engine::Delegate| @@ -807,8 +826,12 @@ void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update, FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetPlatformTaskRunner()->PostTask( - [view = platform_view_->GetWeakPtr(), update = std::move(update), + [shell = GetShell(), update = std::move(update), actions = std::move(actions)] { + if (!shell) { + return; + } + auto view = shell->GetPlatformView(); if (view) { view->UpdateSemantics(std::move(update), std::move(actions)); } @@ -827,7 +850,11 @@ void Shell::OnEngineHandlePlatformMessage( } task_runners_.GetPlatformTaskRunner()->PostTask( - [view = platform_view_->GetWeakPtr(), message = std::move(message)]() { + [shell = GetShell(), message = std::move(message)]() { + if (!shell) { + return; + } + auto view = shell->GetPlatformView(); if (view) { view->HandlePlatformMessage(std::move(message)); } @@ -850,8 +877,11 @@ void Shell::HandleEngineSkiaMessage(fml::RefPtr message) { return; task_runners_.GetGPUTaskRunner()->PostTask( - [rasterizer = rasterizer_->GetWeakPtr(), - max_bytes = args->value.GetInt()] { + [shell = GetShell(), max_bytes = args->value.GetInt()] { + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); if (rasterizer) { rasterizer->SetResourceCacheMaxBytes(max_bytes); } @@ -864,14 +894,17 @@ void Shell::OnPreEngineRestart() { FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); fml::AutoResetWaitableEvent latch; - fml::TaskRunner::RunNowOrPostTask( - task_runners_.GetPlatformTaskRunner(), - [view = platform_view_->GetWeakPtr(), &latch]() { - if (view) { - view->OnPreEngineRestart(); - } - latch.Signal(); - }); + fml::TaskRunner::RunNowOrPostTask(task_runners_.GetPlatformTaskRunner(), + [shell = GetShell(), &latch]() { + if (!shell) { + return; + } + auto view = shell->GetPlatformView(); + if (view) { + view->OnPreEngineRestart(); + } + latch.Signal(); + }); // This is blocking as any embedded platform views has to be flushed before // we re-run the Dart code. latch.Wait(); @@ -894,7 +927,11 @@ void Shell::ReportTimings() { auto timings = std::move(unreported_timings_); unreported_timings_ = {}; - task_runners_.GetUITaskRunner()->PostTask([timings, engine = GetEngine()] { + task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), timings] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->ReportTimings(std::move(timings)); } @@ -953,7 +990,7 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) { // never be reported until the next animation starts. frame_timings_report_scheduled_ = true; task_runners_.GetGPUTaskRunner()->PostDelayedTask( - [self = weak_factory_.GetWeakPtr()]() { + [self = GetShell()]() { if (!self.get()) { return; } @@ -993,8 +1030,8 @@ bool Shell::HandleServiceProtocolMessage( ServiceProtocol::Handler::Description Shell::GetServiceProtocolDescription() const { return { - engine_->GetUIIsolateMainPort(), - engine_->GetUIIsolateName(), + GetEngine()->GetUIIsolateMainPort(), + GetEngine()->GetUIIsolateName(), }; } @@ -1026,7 +1063,7 @@ bool Shell::OnServiceProtocolScreenshot( const ServiceProtocol::Handler::ServiceProtocolMap& params, rapidjson::Document& response) { FML_DCHECK(task_runners_.GetGPUTaskRunner()->RunsTasksOnCurrentThread()); - auto screenshot = rasterizer_->ScreenshotLastLayerTree( + auto screenshot = GetRasterizer()->ScreenshotLastLayerTree( Rasterizer::ScreenshotType::CompressedImage, true); if (screenshot.data) { response.SetObject(); @@ -1047,7 +1084,7 @@ bool Shell::OnServiceProtocolScreenshotSKP( const ServiceProtocol::Handler::ServiceProtocolMap& params, rapidjson::Document& response) { FML_DCHECK(task_runners_.GetGPUTaskRunner()->RunsTasksOnCurrentThread()); - auto screenshot = rasterizer_->ScreenshotLastLayerTree( + auto screenshot = GetRasterizer()->ScreenshotLastLayerTree( Rasterizer::ScreenshotType::SkiaPicture, true); if (screenshot.data) { response.SetObject(); @@ -1113,7 +1150,7 @@ bool Shell::OnServiceProtocolRunInView( auto& allocator = response.GetAllocator(); response.SetObject(); - if (engine_->Restart(std::move(configuration))) { + if (GetEngine()->Restart(std::move(configuration))) { response.AddMember("type", "Success", allocator); auto new_description = GetServiceProtocolDescription(); rapidjson::Value view(rapidjson::kObjectType); @@ -1152,7 +1189,7 @@ bool Shell::OnServiceProtocolGetDisplayRefreshRate( rapidjson::Document& response) { FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); response.SetObject(); - response.AddMember("fps", engine_->GetDisplayRefreshRate(), + response.AddMember("fps", GetEngine()->GetDisplayRefreshRate(), response.GetAllocator()); return true; } @@ -1178,7 +1215,7 @@ bool Shell::OnServiceProtocolSetAssetBundlePath( fml::OpenDirectory(params.at("assetDirectory").ToString().c_str(), false, fml::FilePermission::kRead))); - if (engine_->UpdateAssetManager(std::move(asset_manager))) { + if (GetEngine()->UpdateAssetManager(std::move(asset_manager))) { response.AddMember("type", "Success", allocator); auto new_description = GetServiceProtocolDescription(); rapidjson::Value view(rapidjson::kObjectType); diff --git a/shell/common/shell.h b/shell/common/shell.h index a05ff47e897f8..a406d6c6008d9 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -53,30 +53,21 @@ class Shell final : public PlatformView::Delegate, CreateCallback on_create_platform_view, CreateCallback on_create_rasterizer); - // Creates a shell with the given task runners and settings. The isolate - // snapshot is specified upfront. - static std::unique_ptr Create( - TaskRunners task_runners, - Settings settings, - fml::RefPtr isolate_snapshot, - fml::RefPtr shared_snapshot, - CreateCallback on_create_platform_view, - CreateCallback on_create_rasterizer, - DartVMRef vm); - ~Shell(); const Settings& GetSettings() const; const TaskRunners& GetTaskRunners() const; - fml::WeakPtr GetRasterizer(); + fml::WeakPtr GetRasterizer() const; + + fml::WeakPtr GetEngine() const; - fml::WeakPtr GetEngine(); + fml::WeakPtr GetPlatformView() const; - fml::WeakPtr GetPlatformView(); + fml::WeakPtr GetIOManager() const; - DartVM* GetDartVM(); + fml::WeakPtr GetShell() const; bool IsSetup() const; @@ -90,13 +81,20 @@ class Shell final : public PlatformView::Delegate, const TaskRunners task_runners_; const Settings settings_; - DartVMRef vm_; + DartVM* vm_; + std::unique_ptr platform_view_; // on platform task runner std::unique_ptr engine_; // on UI task runner std::unique_ptr rasterizer_; // on GPU task runner std::unique_ptr io_manager_; // on IO task runner - - fml::WeakPtr weak_engine_; // to be shared across threads + std::promise> platform_view_promise_; + std::promise> engine_promise_; + std::promise> rasterizer_promise_; + std::promise> io_manager_promise_; + std::shared_future> platform_view_future_; + std::shared_future> engine_future_; + std::shared_future> rasterizer_future_; + std::shared_future> io_manager_future_; std::unordered_map, @@ -124,21 +122,14 @@ class Shell final : public PlatformView::Delegate, size_t UnreportedFramesCount() const; Shell(TaskRunners task_runners, Settings settings); - Shell(DartVMRef vm, TaskRunners task_runners, Settings settings); static std::unique_ptr CreateShellOnPlatformThread( - DartVMRef vm, TaskRunners task_runners, Settings settings, - fml::RefPtr isolate_snapshot, - fml::RefPtr shared_snapshot, Shell::CreateCallback on_create_platform_view, Shell::CreateCallback on_create_rasterizer); - bool Setup(std::unique_ptr platform_view, - std::unique_ptr engine, - std::unique_ptr rasterizer, - std::unique_ptr io_manager); + bool Setup(); void ReportTimings(); diff --git a/shell/platform/android/android_shell_holder.cc b/shell/platform/android/android_shell_holder.cc index e9b114fc42252..0de84b2a71255 100644 --- a/shell/platform/android/android_shell_holder.cc +++ b/shell/platform/android/android_shell_holder.cc @@ -158,9 +158,13 @@ void AndroidShellHolder::Launch(RunConfiguration config) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = shell_->GetEngine(), // - config = std::move(config) // + fml::MakeCopyable([shell = shell_->GetShell(), // + config = std::move(config) // ]() mutable { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); FML_LOG(INFO) << "Attempting to launch engine configuration..."; if (!engine || engine->Run(std::move(config)) == Engine::RunStatus::Failure) { @@ -179,7 +183,11 @@ void AndroidShellHolder::SetViewportMetrics( } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = shell_->GetEngine(), metrics]() { + [shell = shell_->GetShell(), metrics]() { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->SetViewportMetrics(metrics); } @@ -195,9 +203,13 @@ void AndroidShellHolder::DispatchPointerDataPacket( TRACE_EVENT0("flutter", "AndroidShellHolder::DispatchPointerDataPacket"); TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_); - shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable( - [engine = shell_->GetEngine(), packet = std::move(packet), - flow_id = next_pointer_flow_id_] { + shell_->GetTaskRunners().GetUITaskRunner()->PostTask( + fml::MakeCopyable([shell = shell_->GetShell(), packet = std::move(packet), + flow_id = next_pointer_flow_id_] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchPointerDataPacket(*packet, flow_id); } diff --git a/shell/platform/embedder/embedder_engine.cc b/shell/platform/embedder/embedder_engine.cc index 79c8cf2f8b672..2589e71fdc7c1 100644 --- a/shell/platform/embedder/embedder_engine.cc +++ b/shell/platform/embedder/embedder_engine.cc @@ -60,9 +60,13 @@ bool EmbedderEngine::Run(RunConfiguration run_configuration) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = shell_->GetEngine(), // engine + fml::MakeCopyable([shell = shell_->GetShell(), // shell config = std::move(run_configuration) // config ]() mutable { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { auto result = engine->Run(std::move(config)); if (result == Engine::RunStatus::Failure) { @@ -80,7 +84,11 @@ bool EmbedderEngine::SetViewportMetrics(flutter::ViewportMetrics metrics) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = shell_->GetEngine(), metrics = std::move(metrics)]() { + [shell = shell_->GetShell(), metrics = std::move(metrics)]() { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->SetViewportMetrics(std::move(metrics)); } @@ -97,9 +105,13 @@ bool EmbedderEngine::DispatchPointerDataPacket( TRACE_EVENT0("flutter", "EmbedderEngine::DispatchPointerDataPacket"); TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_); - shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable( - [engine = shell_->GetEngine(), packet = std::move(packet), - flow_id = next_pointer_flow_id_] { + shell_->GetTaskRunners().GetUITaskRunner()->PostTask( + fml::MakeCopyable([shell = shell_->GetShell(), packet = std::move(packet), + flow_id = next_pointer_flow_id_] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchPointerDataPacket(*packet, flow_id); } @@ -116,7 +128,11 @@ bool EmbedderEngine::SendPlatformMessage( } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = shell_->GetEngine(), message] { + [shell = shell_->GetShell(), message] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchPlatformMessage(message); } @@ -156,7 +172,11 @@ bool EmbedderEngine::SetSemanticsEnabled(bool enabled) { return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = shell_->GetEngine(), enabled] { + [shell = shell_->GetShell(), enabled] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->SetSemanticsEnabled(enabled); } @@ -169,7 +189,11 @@ bool EmbedderEngine::SetAccessibilityFeatures(int32_t flags) { return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [engine = shell_->GetEngine(), flags] { + [shell = shell_->GetShell(), flags] { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->SetAccessibilityFeatures(flags); } @@ -184,11 +208,15 @@ bool EmbedderEngine::DispatchSemanticsAction(int id, return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([engine = shell_->GetEngine(), // engine - id, // id - action, // action - args = std::move(args) // args + fml::MakeCopyable([shell = shell_->GetShell(), // engine + id, // id + action, // action + args = std::move(args) // args ]() mutable { + if (!shell) { + return; + } + auto engine = shell->GetEngine(); if (engine) { engine->DispatchSemanticsAction(id, action, std::move(args)); } From 45affc442ff710108b786a3558828ca7dd43af67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E7=84=B6?= Date: Tue, 18 Jun 2019 15:33:21 +0800 Subject: [PATCH 2/2] use share_ptr for shell --- shell/common/shell.cc | 194 +++++++++++------- shell/common/shell.h | 13 +- shell/common/shell_benchmarks.cc | 2 +- shell/common/shell_test.cc | 4 +- shell/common/shell_test.h | 4 +- shell/common/shell_unittests.cc | 10 +- .../platform/android/android_shell_holder.cc | 15 +- shell/platform/android/android_shell_holder.h | 2 +- shell/platform/embedder/embedder_engine.cc | 31 +-- shell/platform/embedder/embedder_engine.h | 2 +- 10 files changed, 164 insertions(+), 113 deletions(-) diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 830d88ff034a6..558b17c5d3a65 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -35,7 +35,7 @@ namespace flutter { constexpr char kSkiaChannel[] = "flutter/skia"; -std::unique_ptr Shell::CreateShellOnPlatformThread( +std::shared_ptr Shell::CreateShellOnPlatformThread( TaskRunners task_runners, Settings settings, Shell::CreateCallback on_create_platform_view, @@ -45,7 +45,8 @@ std::unique_ptr Shell::CreateShellOnPlatformThread( return nullptr; } - auto shell = std::unique_ptr(new Shell(task_runners, settings)); + auto shell = std::shared_ptr(new Shell(task_runners, settings)); + shell->weak_shell_ = shell; // Create the platform view on the platform thread (this thread). auto platform_view = on_create_platform_view(*shell.get()); @@ -182,7 +183,7 @@ static void PerformInitializationTasks(const Settings& settings) { }); } -std::unique_ptr Shell::Create( +std::shared_ptr Shell::Create( TaskRunners task_runners, Settings settings, Shell::CreateCallback on_create_platform_view, @@ -197,7 +198,7 @@ std::unique_ptr Shell::Create( } fml::AutoResetWaitableEvent latch; - std::unique_ptr shell; + std::shared_ptr shell; fml::TaskRunner::RunNowOrPostTask( task_runners.GetPlatformTaskRunner(), fml::MakeCopyable([&latch, // @@ -275,30 +276,30 @@ Shell::~Shell() { fml::TaskRunner::RunNowOrPostTask( task_runners_.GetUITaskRunner(), - fml::MakeCopyable([shell = GetShell(), &ui_latch]() mutable { - shell->vm_->GetServiceProtocol()->RemoveHandler(shell.get()); - shell->engine_future_.wait(); - shell->engine_.reset(); + fml::MakeCopyable([this, &ui_latch]() mutable { + vm_->GetServiceProtocol()->RemoveHandler(this); + engine_future_.wait(); + engine_.reset(); ui_latch.Signal(); })); ui_latch.Wait(); fml::TaskRunner::RunNowOrPostTask( task_runners_.GetGPUTaskRunner(), - fml::MakeCopyable([shell = GetShell(), &gpu_latch]() mutable { - shell->rasterizer_future_.wait(); - shell->rasterizer_.reset(); + fml::MakeCopyable([this, &gpu_latch]() mutable { + rasterizer_future_.wait(); + rasterizer_.reset(); gpu_latch.Signal(); })); gpu_latch.Wait(); fml::TaskRunner::RunNowOrPostTask( task_runners_.GetIOTaskRunner(), - fml::MakeCopyable([shell = GetShell(), &io_latch]() mutable { - shell->platform_view_future_.wait(); - shell->io_manager_future_.wait(); - shell->io_manager_.reset(); - auto platform_view = shell->platform_view_.get(); + fml::MakeCopyable([this, &io_latch]() mutable { + platform_view_future_.wait(); + io_manager_future_.wait(); + io_manager_.reset(); + auto platform_view = platform_view_.get(); if (platform_view) { platform_view->ReleaseResourceContext(); } @@ -312,8 +313,8 @@ Shell::~Shell() { // example, the NSOpenGLContext on the Mac. fml::TaskRunner::RunNowOrPostTask( task_runners_.GetPlatformTaskRunner(), - fml::MakeCopyable([shell = GetShell(), &platform_latch]() mutable { - shell->platform_view_.reset(); + fml::MakeCopyable([this, &platform_latch]() mutable { + platform_view_.reset(); platform_latch.Signal(); })); platform_latch.Wait(); @@ -387,8 +388,12 @@ fml::WeakPtr Shell::GetPlatformView() const { return {}; } -fml::WeakPtr Shell::GetShell() const { - return weak_factory_.GetWeakPtr(); +std::weak_ptr Shell::GetWeakPtr() const { + return weak_shell_; +} + +DartVM* Shell::GetDartVM() { + return vm_; } // |PlatformView::Delegate| @@ -402,7 +407,8 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { // setup/suspension of all activities that may be interacting with the GPU in // a synchronous fashion. - auto ui_task = [shell = GetShell()] { + auto ui_task = [weak_shell = GetWeakPtr()] { + auto shell = weak_shell.lock(); if (shell) { auto engine = shell->GetEngine(); if (engine) { @@ -413,10 +419,11 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { fml::AutoResetWaitableEvent latch; auto gpu_task = - fml::MakeCopyable([shell = GetShell(), // + fml::MakeCopyable([weak_shell = GetWeakPtr(), // surface = std::move(surface), // ui_task_runner = task_runners_.GetUITaskRunner(), // ui_task, &latch]() mutable { + auto shell = weak_shell.lock(); if (shell) { auto rasterizer = shell->GetRasterizer(); if (rasterizer) { @@ -453,9 +460,10 @@ void Shell::OnPlatformViewCreated(std::unique_ptr surface) { FML_DCHECK(platform_view); - auto io_task = [shell = GetShell(), platform_view, + auto io_task = [weak_shell = GetWeakPtr(), platform_view, gpu_task_runner = task_runners_.GetGPUTaskRunner(), gpu_task, &latch, should_post_gpu_task] { + auto shell = weak_shell.lock(); if (shell) { auto io_manager = shell->GetIOManager(); if (io_manager && !io_manager->GetResourceContext()) { @@ -499,7 +507,9 @@ void Shell::OnPlatformViewDestroyed() { fml::AutoResetWaitableEvent latch; - auto io_task = [io_manager = GetIOManager(), &latch]() { + auto io_task = [weak_shell = GetWeakPtr(), &latch]() { + auto shell = weak_shell.lock(); + auto io_manager = shell->GetIOManager(); if (io_manager) { // Execute any pending Skia object deletions while GPU access is still // allowed. @@ -510,9 +520,11 @@ void Shell::OnPlatformViewDestroyed() { latch.Signal(); }; - auto gpu_task = [rasterizer = GetRasterizer(), + auto gpu_task = [weak_shell = GetWeakPtr(), io_task_runner = task_runners_.GetIOTaskRunner(), io_task]() { + auto shell = weak_shell.lock(); + auto rasterizer = shell->GetRasterizer(); if (rasterizer) { rasterizer->Teardown(); } @@ -532,9 +544,11 @@ void Shell::OnPlatformViewDestroyed() { bool should_post_gpu_task = task_runners_.GetGPUTaskRunner() != task_runners_.GetPlatformTaskRunner(); - auto ui_task = [engine = GetEngine(), + auto ui_task = [weak_shell = GetWeakPtr(), gpu_task_runner = task_runners_.GetGPUTaskRunner(), gpu_task, should_post_gpu_task, &latch]() { + auto shell = weak_shell.lock(); + auto engine = shell->GetEngine(); if (engine) { engine->OnOutputSurfaceDestroyed(); } @@ -567,15 +581,17 @@ void Shell::OnPlatformViewSetViewportMetrics(const ViewportMetrics& metrics) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), metrics]() { - if (!shell) { - return; - } - auto engine = shell->GetEngine(); - if (engine) { - engine->SetViewportMetrics(metrics); - } - }); + task_runners_.GetUITaskRunner()->PostTask( + [weak_shell = GetWeakPtr(), metrics]() { + auto shell = weak_shell.lock(); + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->SetViewportMetrics(metrics); + } + }); } // |PlatformView::Delegate| @@ -585,7 +601,8 @@ void Shell::OnPlatformViewDispatchPlatformMessage( FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetUITaskRunner()->PostTask( - [shell = GetShell(), message = std::move(message)] { + [weak_shell = GetWeakPtr(), message = std::move(message)] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -604,8 +621,9 @@ void Shell::OnPlatformViewDispatchPointerDataPacket( FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = GetShell(), packet = std::move(packet), + fml::MakeCopyable([weak_shell = GetWeakPtr(), packet = std::move(packet), flow_id = next_pointer_flow_id_] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -625,7 +643,8 @@ void Shell::OnPlatformViewDispatchSemanticsAction(int32_t id, FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetUITaskRunner()->PostTask( - [shell = GetShell(), id, action, args = std::move(args)] { + [weak_shell = GetWeakPtr(), id, action, args = std::move(args)] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -641,15 +660,17 @@ void Shell::OnPlatformViewSetSemanticsEnabled(bool enabled) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), enabled] { - if (!shell) { - return; - } - auto engine = shell->GetEngine(); - if (engine) { - engine->SetSemanticsEnabled(enabled); - } - }); + task_runners_.GetUITaskRunner()->PostTask( + [weak_shell = GetWeakPtr(), enabled] { + auto shell = weak_shell.lock(); + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->SetSemanticsEnabled(enabled); + } + }); } // |PlatformView::Delegate| @@ -657,7 +678,8 @@ void Shell::OnPlatformViewSetAccessibilityFeatures(int32_t flags) { FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), flags] { + task_runners_.GetUITaskRunner()->PostTask([weak_shell = GetWeakPtr(), flags] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -674,17 +696,19 @@ void Shell::OnPlatformViewRegisterTexture( FML_DCHECK(is_setup_); FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); - task_runners_.GetGPUTaskRunner()->PostTask([shell = GetShell(), texture] { - if (!shell) { - return; - } - auto rasterizer = shell->GetRasterizer(); - if (rasterizer) { - if (auto* registry = rasterizer->GetTextureRegistry()) { - registry->RegisterTexture(texture); - } - } - }); + task_runners_.GetGPUTaskRunner()->PostTask( + [weak_shell = GetWeakPtr(), texture] { + auto shell = weak_shell.lock(); + if (!shell) { + return; + } + auto rasterizer = shell->GetRasterizer(); + if (rasterizer) { + if (auto* registry = rasterizer->GetTextureRegistry()) { + registry->RegisterTexture(texture); + } + } + }); } // |PlatformView::Delegate| @@ -693,7 +717,8 @@ void Shell::OnPlatformViewUnregisterTexture(int64_t texture_id) { FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetGPUTaskRunner()->PostTask( - [shell = GetShell(), texture_id]() { + [weak_shell = GetWeakPtr(), texture_id]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -713,7 +738,8 @@ void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) { // Tell the rasterizer that one of its textures has a new frame available. task_runners_.GetGPUTaskRunner()->PostTask( - [shell = GetShell(), texture_id]() { + [weak_shell = GetWeakPtr(), texture_id]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -738,7 +764,8 @@ void Shell::OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) { }); // Schedule a new frame without having to rebuild the layer tree. - task_runners_.GetUITaskRunner()->PostTask([shell = GetShell()]() { + task_runners_.GetUITaskRunner()->PostTask([weak_shell = GetWeakPtr()]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -755,7 +782,8 @@ void Shell::OnPlatformViewSetNextFrameCallback(fml::closure closure) { FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetGPUTaskRunner()->PostTask( - [shell = GetShell(), closure = std::move(closure)]() { + [weak_shell = GetWeakPtr(), closure = std::move(closure)]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -793,7 +821,8 @@ void Shell::OnAnimatorDraw(fml::RefPtr> pipeline) { FML_DCHECK(is_setup_); task_runners_.GetGPUTaskRunner()->PostTask( - [shell = GetShell(), pipeline = std::move(pipeline)]() { + [weak_shell = GetWeakPtr(), pipeline = std::move(pipeline)]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -808,7 +837,8 @@ void Shell::OnAnimatorDraw(fml::RefPtr> pipeline) { void Shell::OnAnimatorDrawLastLayerTree() { FML_DCHECK(is_setup_); - task_runners_.GetGPUTaskRunner()->PostTask([shell = GetShell()]() { + task_runners_.GetGPUTaskRunner()->PostTask([weak_shell = GetWeakPtr()]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -826,8 +856,9 @@ void Shell::OnEngineUpdateSemantics(SemanticsNodeUpdates update, FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread()); task_runners_.GetPlatformTaskRunner()->PostTask( - [shell = GetShell(), update = std::move(update), + [weak_shell = GetWeakPtr(), update = std::move(update), actions = std::move(actions)] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -850,7 +881,8 @@ void Shell::OnEngineHandlePlatformMessage( } task_runners_.GetPlatformTaskRunner()->PostTask( - [shell = GetShell(), message = std::move(message)]() { + [weak_shell = GetWeakPtr(), message = std::move(message)]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -877,7 +909,8 @@ void Shell::HandleEngineSkiaMessage(fml::RefPtr message) { return; task_runners_.GetGPUTaskRunner()->PostTask( - [shell = GetShell(), max_bytes = args->value.GetInt()] { + [weak_shell = GetWeakPtr(), max_bytes = args->value.GetInt()] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -895,7 +928,8 @@ void Shell::OnPreEngineRestart() { fml::AutoResetWaitableEvent latch; fml::TaskRunner::RunNowOrPostTask(task_runners_.GetPlatformTaskRunner(), - [shell = GetShell(), &latch]() { + [weak_shell = GetWeakPtr(), &latch]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -927,15 +961,17 @@ void Shell::ReportTimings() { auto timings = std::move(unreported_timings_); unreported_timings_ = {}; - task_runners_.GetUITaskRunner()->PostTask([shell = GetShell(), timings] { - if (!shell) { - return; - } - auto engine = shell->GetEngine(); - if (engine) { - engine->ReportTimings(std::move(timings)); - } - }); + task_runners_.GetUITaskRunner()->PostTask( + [weak_shell = GetWeakPtr(), timings] { + auto shell = weak_shell.lock(); + if (!shell) { + return; + } + auto engine = shell->GetEngine(); + if (engine) { + engine->ReportTimings(std::move(timings)); + } + }); } size_t Shell::UnreportedFramesCount() const { @@ -990,7 +1026,7 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) { // never be reported until the next animation starts. frame_timings_report_scheduled_ = true; task_runners_.GetGPUTaskRunner()->PostDelayedTask( - [self = GetShell()]() { + [self = weak_factory_.GetWeakPtr()]() { if (!self.get()) { return; } diff --git a/shell/common/shell.h b/shell/common/shell.h index a406d6c6008d9..b8562aec751b2 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -40,14 +40,15 @@ class Shell final : public PlatformView::Delegate, public Animator::Delegate, public Engine::Delegate, public Rasterizer::Delegate, - public ServiceProtocol::Handler { + public ServiceProtocol::Handler, + public std::enable_shared_from_this { public: template using CreateCallback = std::function(Shell&)>; // Create a shell with the given task runners and settings. The isolate // snapshot will be shared with the snapshot of the service isolate. - static std::unique_ptr Create( + static std::shared_ptr Create( TaskRunners task_runners, Settings settings, CreateCallback on_create_platform_view, @@ -67,7 +68,10 @@ class Shell final : public PlatformView::Delegate, fml::WeakPtr GetIOManager() const; - fml::WeakPtr GetShell() const; + // for access Shell in a closure + std::weak_ptr GetWeakPtr() const; + + DartVM* GetDartVM(); bool IsSetup() const; @@ -83,6 +87,7 @@ class Shell final : public PlatformView::Delegate, const Settings settings_; DartVM* vm_; + std::weak_ptr weak_shell_; std::unique_ptr platform_view_; // on platform task runner std::unique_ptr engine_; // on UI task runner std::unique_ptr rasterizer_; // on GPU task runner @@ -123,7 +128,7 @@ class Shell final : public PlatformView::Delegate, Shell(TaskRunners task_runners, Settings settings); - static std::unique_ptr CreateShellOnPlatformThread( + static std::shared_ptr CreateShellOnPlatformThread( TaskRunners task_runners, Settings settings, Shell::CreateCallback on_create_platform_view, diff --git a/shell/common/shell_benchmarks.cc b/shell/common/shell_benchmarks.cc index c101cd3a4fb56..248b0ffba709d 100644 --- a/shell/common/shell_benchmarks.cc +++ b/shell/common/shell_benchmarks.cc @@ -12,7 +12,7 @@ namespace flutter { static void StartupAndShutdownShell(benchmark::State& state, bool measure_startup, bool measure_shutdown) { - std::unique_ptr shell; + std::shared_ptr shell; std::unique_ptr thread_host; { benchmarking::ScopedPauseTiming pause(state, !measure_startup); diff --git a/shell/common/shell_test.cc b/shell/common/shell_test.cc index 9afd64ad165f3..ca180483da7bb 100644 --- a/shell/common/shell_test.cc +++ b/shell/common/shell_test.cc @@ -152,11 +152,11 @@ TaskRunners ShellTest::GetTaskRunnersForFixture() { }; } -std::unique_ptr ShellTest::CreateShell(Settings settings) { +std::shared_ptr ShellTest::CreateShell(Settings settings) { return CreateShell(std::move(settings), GetTaskRunnersForFixture()); } -std::unique_ptr ShellTest::CreateShell(Settings settings, +std::shared_ptr ShellTest::CreateShell(Settings settings, TaskRunners task_runners) { return Shell::Create( task_runners, settings, diff --git a/shell/common/shell_test.h b/shell/common/shell_test.h index 2a839b821e6e1..c922604ba74b2 100644 --- a/shell/common/shell_test.h +++ b/shell/common/shell_test.h @@ -26,8 +26,8 @@ class ShellTest : public ThreadTest { ~ShellTest(); Settings CreateSettingsForFixture(); - std::unique_ptr CreateShell(Settings settings); - std::unique_ptr CreateShell(Settings settings, + std::shared_ptr CreateShell(Settings settings); + std::shared_ptr CreateShell(Settings settings, TaskRunners task_runners); TaskRunners GetTaskRunnersForFixture(); diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index dcc3c7a8e7c6e..ebc7b3bf2706e 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -253,7 +253,7 @@ TEST_F(ShellTest, WhitelistedDartVMFlag) { TEST_F(ShellTest, NoNeedToReportTimingsByDefault) { auto settings = CreateSettingsForFixture(); - std::unique_ptr shell = CreateShell(std::move(settings)); + std::shared_ptr shell = CreateShell(std::move(settings)); // Create the surface needed by rasterizer PlatformViewNotifyCreated(shell.get()); @@ -280,7 +280,7 @@ TEST_F(ShellTest, NoNeedToReportTimingsByDefault) { TEST_F(ShellTest, NeedsReportTimingsIsSetWithCallback) { auto settings = CreateSettingsForFixture(); - std::unique_ptr shell = CreateShell(std::move(settings)); + std::shared_ptr shell = CreateShell(std::move(settings)); // Create the surface needed by rasterizer PlatformViewNotifyCreated(shell.get()); @@ -317,7 +317,7 @@ static void CheckFrameTimings(const std::vector& timings, TEST_F(ShellTest, ReportTimingsIsCalled) { fml::TimePoint start = fml::TimePoint::Now(); auto settings = CreateSettingsForFixture(); - std::unique_ptr shell = CreateShell(std::move(settings)); + std::shared_ptr shell = CreateShell(std::move(settings)); // Create the surface needed by rasterizer PlatformViewNotifyCreated(shell.get()); @@ -383,7 +383,7 @@ TEST_F(ShellTest, FrameRasterizedCallbackIsCalled) { timingLatch.Signal(); }; - std::unique_ptr shell = CreateShell(std::move(settings)); + std::shared_ptr shell = CreateShell(std::move(settings)); // Create the surface needed by rasterizer PlatformViewNotifyCreated(shell.get()); @@ -441,7 +441,7 @@ TEST_F(ShellTest, ReportTimingsIsCalledLaterInNonReleaseMode) { #endif fml::TimePoint start = fml::TimePoint::Now(); auto settings = CreateSettingsForFixture(); - std::unique_ptr shell = CreateShell(std::move(settings)); + std::shared_ptr shell = CreateShell(std::move(settings)); // Create the surface needed by rasterizer PlatformViewNotifyCreated(shell.get()); diff --git a/shell/platform/android/android_shell_holder.cc b/shell/platform/android/android_shell_holder.cc index 0de84b2a71255..4ebb5a4fdefae 100644 --- a/shell/platform/android/android_shell_holder.cc +++ b/shell/platform/android/android_shell_holder.cc @@ -158,9 +158,10 @@ void AndroidShellHolder::Launch(RunConfiguration config) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = shell_->GetShell(), // - config = std::move(config) // + fml::MakeCopyable([weak_shell = shell_->GetWeakPtr(), // + config = std::move(config) // ]() mutable { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -183,7 +184,8 @@ void AndroidShellHolder::SetViewportMetrics( } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [shell = shell_->GetShell(), metrics]() { + [weak_shell = shell_->GetWeakPtr(), metrics]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -203,9 +205,10 @@ void AndroidShellHolder::DispatchPointerDataPacket( TRACE_EVENT0("flutter", "AndroidShellHolder::DispatchPointerDataPacket"); TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_); - shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = shell_->GetShell(), packet = std::move(packet), - flow_id = next_pointer_flow_id_] { + shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable( + [weak_shell = shell_->GetWeakPtr(), packet = std::move(packet), + flow_id = next_pointer_flow_id_] { + auto shell = weak_shell.lock(); if (!shell) { return; } diff --git a/shell/platform/android/android_shell_holder.h b/shell/platform/android/android_shell_holder.h index ce966ebb6da66..4d8e0d70f5bfc 100644 --- a/shell/platform/android/android_shell_holder.h +++ b/shell/platform/android/android_shell_holder.h @@ -49,7 +49,7 @@ class AndroidShellHolder { const fml::jni::JavaObjectWeakGlobalRef java_object_; fml::WeakPtr platform_view_; ThreadHost thread_host_; - std::unique_ptr shell_; + std::shared_ptr shell_; bool is_valid_ = false; pthread_key_t thread_destruct_key_; uint64_t next_pointer_flow_id_ = 0; diff --git a/shell/platform/embedder/embedder_engine.cc b/shell/platform/embedder/embedder_engine.cc index 2589e71fdc7c1..261cc2cb306c6 100644 --- a/shell/platform/embedder/embedder_engine.cc +++ b/shell/platform/embedder/embedder_engine.cc @@ -60,9 +60,10 @@ bool EmbedderEngine::Run(RunConfiguration run_configuration) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = shell_->GetShell(), // shell + fml::MakeCopyable([weak_shell = shell_->GetWeakPtr(), // shell config = std::move(run_configuration) // config ]() mutable { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -84,7 +85,8 @@ bool EmbedderEngine::SetViewportMetrics(flutter::ViewportMetrics metrics) { } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [shell = shell_->GetShell(), metrics = std::move(metrics)]() { + [weak_shell = shell_->GetWeakPtr(), metrics = std::move(metrics)]() { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -105,9 +107,10 @@ bool EmbedderEngine::DispatchPointerDataPacket( TRACE_EVENT0("flutter", "EmbedderEngine::DispatchPointerDataPacket"); TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_); - shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = shell_->GetShell(), packet = std::move(packet), - flow_id = next_pointer_flow_id_] { + shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable( + [weak_shell = shell_->GetWeakPtr(), packet = std::move(packet), + flow_id = next_pointer_flow_id_] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -128,7 +131,8 @@ bool EmbedderEngine::SendPlatformMessage( } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [shell = shell_->GetShell(), message] { + [weak_shell = shell_->GetWeakPtr(), message] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -172,7 +176,8 @@ bool EmbedderEngine::SetSemanticsEnabled(bool enabled) { return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [shell = shell_->GetShell(), enabled] { + [weak_shell = shell_->GetWeakPtr(), enabled] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -189,7 +194,8 @@ bool EmbedderEngine::SetAccessibilityFeatures(int32_t flags) { return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - [shell = shell_->GetShell(), flags] { + [weak_shell = shell_->GetWeakPtr(), flags] { + auto shell = weak_shell.lock(); if (!shell) { return; } @@ -208,11 +214,12 @@ bool EmbedderEngine::DispatchSemanticsAction(int id, return false; } shell_->GetTaskRunners().GetUITaskRunner()->PostTask( - fml::MakeCopyable([shell = shell_->GetShell(), // engine - id, // id - action, // action - args = std::move(args) // args + fml::MakeCopyable([weak_shell = shell_->GetWeakPtr(), // engine + id, // id + action, // action + args = std::move(args) // args ]() mutable { + auto shell = weak_shell.lock(); if (!shell) { return; } diff --git a/shell/platform/embedder/embedder_engine.h b/shell/platform/embedder/embedder_engine.h index ab962066ea0d9..4f6005a043a46 100644 --- a/shell/platform/embedder/embedder_engine.h +++ b/shell/platform/embedder/embedder_engine.h @@ -71,7 +71,7 @@ class EmbedderEngine { private: const std::unique_ptr thread_host_; - std::unique_ptr shell_; + std::shared_ptr shell_; const EmbedderExternalTextureGL::ExternalTextureCallback external_texture_callback_; bool is_valid_ = false;