Share the io_manager between parent and spawn engine (flutter/engine#29915)
This commit is contained in:
@@ -48,7 +48,15 @@ std::unique_ptr<RuntimeController> RuntimeController::Spawn(
|
||||
const std::function<void(int64_t)>& p_idle_notification_callback,
|
||||
const fml::closure& p_isolate_create_callback,
|
||||
const fml::closure& p_isolate_shutdown_callback,
|
||||
std::shared_ptr<const fml::Mapping> p_persistent_isolate_data) const {
|
||||
std::shared_ptr<const fml::Mapping> p_persistent_isolate_data,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::WeakPtr<ImageDecoder> image_decoder) const {
|
||||
UIDartState::Context spawned_context{
|
||||
context_.task_runners, context_.snapshot_delegate,
|
||||
std::move(io_manager), context_.unref_queue,
|
||||
std::move(image_decoder), context_.image_generator_registry,
|
||||
advisory_script_uri, advisory_script_entrypoint,
|
||||
context_.volatile_path_tracker};
|
||||
auto result =
|
||||
std::make_unique<RuntimeController>(p_client, //
|
||||
vm_, //
|
||||
@@ -58,7 +66,7 @@ std::unique_ptr<RuntimeController> RuntimeController::Spawn(
|
||||
p_isolate_create_callback, //
|
||||
p_isolate_shutdown_callback, //
|
||||
p_persistent_isolate_data, //
|
||||
context_); //
|
||||
spawned_context); //
|
||||
result->spawning_isolate_ = root_isolate_;
|
||||
result->platform_data_.viewport_metrics = ViewportMetrics();
|
||||
return result;
|
||||
|
||||
@@ -102,7 +102,9 @@ class RuntimeController : public PlatformConfigurationClient {
|
||||
const std::function<void(int64_t)>& idle_notification_callback,
|
||||
const fml::closure& isolate_create_callback,
|
||||
const fml::closure& isolate_shutdown_callback,
|
||||
std::shared_ptr<const fml::Mapping> persistent_isolate_data) const;
|
||||
std::shared_ptr<const fml::Mapping> persistent_isolate_data,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::WeakPtr<ImageDecoder> image_decoder) const;
|
||||
|
||||
// |PlatformConfigurationClient|
|
||||
~RuntimeController() override;
|
||||
|
||||
@@ -107,7 +107,8 @@ std::unique_ptr<Engine> Engine::Spawn(
|
||||
const PointerDataDispatcherMaker& dispatcher_maker,
|
||||
Settings settings,
|
||||
std::unique_ptr<Animator> animator,
|
||||
const std::string& initial_route) const {
|
||||
const std::string& initial_route,
|
||||
fml::WeakPtr<IOManager> io_manager) const {
|
||||
auto result = std::make_unique<Engine>(
|
||||
/*delegate=*/delegate,
|
||||
/*dispatcher_maker=*/dispatcher_maker,
|
||||
@@ -116,7 +117,7 @@ std::unique_ptr<Engine> Engine::Spawn(
|
||||
/*task_runners=*/task_runners_,
|
||||
/*settings=*/settings,
|
||||
/*animator=*/std::move(animator),
|
||||
/*io_manager=*/runtime_controller_->GetIOManager(),
|
||||
/*io_manager=*/io_manager,
|
||||
/*font_collection=*/font_collection_,
|
||||
/*runtime_controller=*/nullptr);
|
||||
result->runtime_controller_ = runtime_controller_->Spawn(
|
||||
@@ -126,7 +127,9 @@ std::unique_ptr<Engine> Engine::Spawn(
|
||||
settings_.idle_notification_callback, // idle notification callback
|
||||
settings_.isolate_create_callback, // isolate create callback
|
||||
settings_.isolate_shutdown_callback, // isolate shutdown callback
|
||||
settings_.persistent_isolate_data // persistent isolate data
|
||||
settings_.persistent_isolate_data, // persistent isolate data
|
||||
io_manager, // io_manager
|
||||
result->GetImageDecoderWeakPtr() // imageDecoder
|
||||
);
|
||||
result->initial_route_ = initial_route;
|
||||
return result;
|
||||
@@ -147,6 +150,10 @@ std::shared_ptr<AssetManager> Engine::GetAssetManager() {
|
||||
return asset_manager_;
|
||||
}
|
||||
|
||||
fml::WeakPtr<ImageDecoder> Engine::GetImageDecoderWeakPtr() {
|
||||
return image_decoder_.GetWeakPtr();
|
||||
}
|
||||
|
||||
fml::WeakPtr<ImageGeneratorRegistry> Engine::GetImageGeneratorRegistry() {
|
||||
return image_generator_registry_.GetWeakPtr();
|
||||
}
|
||||
|
||||
@@ -376,7 +376,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
const PointerDataDispatcherMaker& dispatcher_maker,
|
||||
Settings settings,
|
||||
std::unique_ptr<Animator> animator,
|
||||
const std::string& initial_route) const;
|
||||
const std::string& initial_route,
|
||||
fml::WeakPtr<IOManager> io_manager) const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Destroys the engine engine. Called by the shell on the UI task
|
||||
@@ -791,6 +792,9 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
// Return the asset manager associated with the current engine, or nullptr.
|
||||
std::shared_ptr<AssetManager> GetAssetManager();
|
||||
|
||||
// Return the weak_ptr of ImageDecoder.
|
||||
fml::WeakPtr<ImageDecoder> GetImageDecoderWeakPtr();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Get the `ImageGeneratorRegistry` associated with the current
|
||||
/// engine.
|
||||
|
||||
@@ -269,7 +269,7 @@ TEST_F(EngineTest, SpawnSharesFontLibrary) {
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string());
|
||||
std::string(), io_manager_);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
EXPECT_EQ(&engine->GetFontCollection(), &spawn->GetFontCollection());
|
||||
});
|
||||
@@ -294,8 +294,8 @@ TEST_F(EngineTest, SpawnWithCustomInitialRoute) {
|
||||
/*font_collection=*/std::make_shared<FontCollection>(),
|
||||
/*runtime_controller=*/std::move(mock_runtime_controller));
|
||||
|
||||
auto spawn =
|
||||
engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr, "/foo");
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
"/foo", io_manager_);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
ASSERT_EQ("/foo", spawn->InitialRoute());
|
||||
});
|
||||
@@ -331,7 +331,7 @@ TEST_F(EngineTest, SpawnResetsViewportMetrics) {
|
||||
EXPECT_EQ(old_platform_data.viewport_metrics.physical_height, kViewHeight);
|
||||
|
||||
auto spawn = engine->Spawn(delegate_, dispatcher_maker_, settings_, nullptr,
|
||||
std::string());
|
||||
std::string(), io_manager_);
|
||||
EXPECT_TRUE(spawn != nullptr);
|
||||
auto& new_viewport_metrics =
|
||||
spawn->GetRuntimeController()->GetPlatformData().viewport_metrics;
|
||||
|
||||
@@ -150,6 +150,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
return CreateWithSnapshot(std::move(platform_data), //
|
||||
std::move(task_runners), //
|
||||
/*parent_merger=*/nullptr, //
|
||||
/*parent_io_manager=*/nullptr, //
|
||||
std::move(settings), //
|
||||
std::move(vm), //
|
||||
std::move(isolate_snapshot), //
|
||||
@@ -161,6 +162,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
DartVMRef vm,
|
||||
fml::RefPtr<fml::RasterThreadMerger> parent_merger,
|
||||
std::shared_ptr<ShellIOManager> parent_io_manager,
|
||||
TaskRunners task_runners,
|
||||
const PlatformData& platform_data,
|
||||
Settings settings,
|
||||
@@ -215,7 +217,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
// 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.
|
||||
std::promise<std::unique_ptr<ShellIOManager>> io_manager_promise;
|
||||
std::promise<std::shared_ptr<ShellIOManager>> io_manager_promise;
|
||||
auto io_manager_future = io_manager_promise.get_future();
|
||||
std::promise<fml::WeakPtr<ShellIOManager>> weak_io_manager_promise;
|
||||
auto weak_io_manager_future = weak_io_manager_promise.get_future();
|
||||
@@ -230,18 +232,24 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
io_task_runner,
|
||||
[&io_manager_promise, //
|
||||
&weak_io_manager_promise, //
|
||||
&parent_io_manager, //
|
||||
&unref_queue_promise, //
|
||||
platform_view_ptr, //
|
||||
io_task_runner, //
|
||||
is_backgrounded_sync_switch = shell->GetIsGpuDisabledSyncSwitch() //
|
||||
]() {
|
||||
TRACE_EVENT0("flutter", "ShellSetupIOSubsystem");
|
||||
auto io_manager = std::make_unique<ShellIOManager>(
|
||||
platform_view_ptr->CreateResourceContext(),
|
||||
is_backgrounded_sync_switch, io_task_runner);
|
||||
std::shared_ptr<ShellIOManager> io_manager;
|
||||
if (parent_io_manager) {
|
||||
io_manager = parent_io_manager;
|
||||
} else {
|
||||
io_manager = std::make_shared<ShellIOManager>(
|
||||
platform_view_ptr->CreateResourceContext(),
|
||||
is_backgrounded_sync_switch, io_task_runner);
|
||||
}
|
||||
weak_io_manager_promise.set_value(io_manager->GetWeakPtr());
|
||||
unref_queue_promise.set_value(io_manager->GetSkiaUnrefQueue());
|
||||
io_manager_promise.set_value(std::move(io_manager));
|
||||
io_manager_promise.set_value(io_manager);
|
||||
});
|
||||
|
||||
// Send dispatcher_maker to the engine constructor because shell won't have
|
||||
@@ -301,6 +309,7 @@ std::unique_ptr<Shell> Shell::CreateWithSnapshot(
|
||||
const PlatformData& platform_data,
|
||||
TaskRunners task_runners,
|
||||
fml::RefPtr<fml::RasterThreadMerger> parent_thread_merger,
|
||||
std::shared_ptr<ShellIOManager> parent_io_manager,
|
||||
Settings settings,
|
||||
DartVMRef vm,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
@@ -327,6 +336,7 @@ std::unique_ptr<Shell> Shell::CreateWithSnapshot(
|
||||
[&latch, //
|
||||
&shell, //
|
||||
parent_thread_merger, //
|
||||
parent_io_manager, //
|
||||
task_runners = std::move(task_runners), //
|
||||
platform_data = std::move(platform_data), //
|
||||
settings = std::move(settings), //
|
||||
@@ -339,6 +349,7 @@ std::unique_ptr<Shell> Shell::CreateWithSnapshot(
|
||||
shell = CreateShellOnPlatformThread(
|
||||
std::move(vm), //
|
||||
parent_thread_merger, //
|
||||
parent_io_manager, //
|
||||
std::move(task_runners), //
|
||||
std::move(platform_data), //
|
||||
std::move(settings), //
|
||||
@@ -486,9 +497,9 @@ std::unique_ptr<Shell> Shell::Spawn(
|
||||
fml::SyncSwitch::Handlers()
|
||||
.SetIfFalse([&is_gpu_disabled] { is_gpu_disabled = false; })
|
||||
.SetIfTrue([&is_gpu_disabled] { is_gpu_disabled = true; }));
|
||||
std::unique_ptr<Shell> result = (CreateWithSnapshot(
|
||||
std::unique_ptr<Shell> result = CreateWithSnapshot(
|
||||
PlatformData{}, task_runners_, rasterizer_->GetRasterThreadMerger(),
|
||||
GetSettings(), vm_, vm_->GetVMData()->GetIsolateSnapshot(),
|
||||
io_manager_, GetSettings(), vm_, vm_->GetVMData()->GetIsolateSnapshot(),
|
||||
on_create_platform_view, on_create_rasterizer,
|
||||
[engine = this->engine_.get(), initial_route](
|
||||
Engine::Delegate& delegate,
|
||||
@@ -504,9 +515,10 @@ std::unique_ptr<Shell> Shell::Spawn(
|
||||
/*dispatcher_maker=*/dispatcher_maker,
|
||||
/*settings=*/settings,
|
||||
/*animator=*/std::move(animator),
|
||||
/*initial_route=*/initial_route);
|
||||
/*initial_route=*/initial_route,
|
||||
/*io_manager=*/std::move(io_manager));
|
||||
},
|
||||
is_gpu_disabled));
|
||||
is_gpu_disabled);
|
||||
result->shared_resource_context_ = io_manager_->GetSharedResourceContext();
|
||||
result->RunEngine(std::move(run_configuration));
|
||||
return result;
|
||||
@@ -609,7 +621,7 @@ bool Shell::IsSetup() const {
|
||||
bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
|
||||
std::unique_ptr<Engine> engine,
|
||||
std::unique_ptr<Rasterizer> rasterizer,
|
||||
std::unique_ptr<ShellIOManager> io_manager) {
|
||||
std::shared_ptr<ShellIOManager> io_manager) {
|
||||
if (is_setup_) {
|
||||
return false;
|
||||
}
|
||||
@@ -622,7 +634,7 @@ bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
|
||||
platform_message_handler_ = platform_view_->GetPlatformMessageHandler();
|
||||
engine_ = std::move(engine);
|
||||
rasterizer_ = std::move(rasterizer);
|
||||
io_manager_ = std::move(io_manager);
|
||||
io_manager_ = io_manager;
|
||||
|
||||
// Set the external view embedder for the rasterizer.
|
||||
auto view_embedder = platform_view_->CreateExternalViewEmbedder();
|
||||
|
||||
@@ -415,7 +415,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
std::unique_ptr<PlatformView> platform_view_; // on platform task runner
|
||||
std::unique_ptr<Engine> engine_; // on UI task runner
|
||||
std::unique_ptr<Rasterizer> rasterizer_; // on raster task runner
|
||||
std::unique_ptr<ShellIOManager> io_manager_; // on IO task runner
|
||||
std::shared_ptr<ShellIOManager> io_manager_; // on IO task runner
|
||||
std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch_;
|
||||
std::shared_ptr<VolatilePathTracker> volatile_path_tracker_;
|
||||
std::shared_ptr<PlatformMessageHandler> platform_message_handler_;
|
||||
@@ -480,6 +480,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
static std::unique_ptr<Shell> CreateShellOnPlatformThread(
|
||||
DartVMRef vm,
|
||||
fml::RefPtr<fml::RasterThreadMerger> parent_merger,
|
||||
std::shared_ptr<ShellIOManager> parent_io_manager,
|
||||
TaskRunners task_runners,
|
||||
const PlatformData& platform_data,
|
||||
Settings settings,
|
||||
@@ -492,6 +493,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
const PlatformData& platform_data,
|
||||
TaskRunners task_runners,
|
||||
fml::RefPtr<fml::RasterThreadMerger> parent_thread_merger,
|
||||
std::shared_ptr<ShellIOManager> parent_io_manager,
|
||||
Settings settings,
|
||||
DartVMRef vm,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
@@ -503,7 +505,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
bool Setup(std::unique_ptr<PlatformView> platform_view,
|
||||
std::unique_ptr<Engine> engine,
|
||||
std::unique_ptr<Rasterizer> rasterizer,
|
||||
std::unique_ptr<ShellIOManager> io_manager);
|
||||
std::shared_ptr<ShellIOManager> io_manager);
|
||||
|
||||
void ReportTimings();
|
||||
|
||||
|
||||
@@ -2960,6 +2960,107 @@ TEST_F(ShellTest, SpawnWithDartEntrypointArgs) {
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, IOManagerIsSharedBetweenParentAndSpawnedShell) {
|
||||
auto settings = CreateSettingsForFixture();
|
||||
auto shell = CreateShell(settings);
|
||||
ASSERT_TRUE(ValidateShell(shell.get()));
|
||||
|
||||
PostSync(shell->GetTaskRunners().GetPlatformTaskRunner(), [this,
|
||||
&spawner = shell,
|
||||
&settings] {
|
||||
auto second_configuration = RunConfiguration::InferFromSettings(settings);
|
||||
ASSERT_TRUE(second_configuration.IsValid());
|
||||
second_configuration.SetEntrypoint("emptyMain");
|
||||
const std::string initial_route("/foo");
|
||||
MockPlatformViewDelegate platform_view_delegate;
|
||||
auto spawn = spawner->Spawn(
|
||||
std::move(second_configuration), initial_route,
|
||||
[&platform_view_delegate](Shell& shell) {
|
||||
auto result = std::make_unique<MockPlatformView>(
|
||||
platform_view_delegate, shell.GetTaskRunners());
|
||||
ON_CALL(*result, CreateRenderingSurface())
|
||||
.WillByDefault(::testing::Invoke(
|
||||
[] { return std::make_unique<MockSurface>(); }));
|
||||
return result;
|
||||
},
|
||||
[](Shell& shell) { return std::make_unique<Rasterizer>(shell); });
|
||||
ASSERT_TRUE(ValidateShell(spawn.get()));
|
||||
|
||||
PostSync(spawner->GetTaskRunners().GetIOTaskRunner(), [&spawner, &spawn] {
|
||||
ASSERT_NE(spawner->GetIOManager().get(), nullptr);
|
||||
ASSERT_EQ(spawner->GetIOManager().get(), spawn->GetIOManager().get());
|
||||
});
|
||||
|
||||
// Destroy the child shell.
|
||||
DestroyShell(std::move(spawn));
|
||||
});
|
||||
// Destroy the parent shell.
|
||||
DestroyShell(std::move(shell));
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, IOManagerInSpawnedShellIsNotNullAfterParentShellDestroyed) {
|
||||
auto settings = CreateSettingsForFixture();
|
||||
auto shell = CreateShell(settings);
|
||||
ASSERT_TRUE(ValidateShell(shell.get()));
|
||||
|
||||
PostSync(shell->GetTaskRunners().GetUITaskRunner(), [&shell] {
|
||||
// We must get engine on UI thread.
|
||||
auto runtime_controller = shell->GetEngine()->GetRuntimeController();
|
||||
PostSync(shell->GetTaskRunners().GetIOTaskRunner(),
|
||||
[&shell, &runtime_controller] {
|
||||
// We must get io_manager on IO thread.
|
||||
auto io_manager = runtime_controller->GetIOManager();
|
||||
// Check io_manager existence.
|
||||
ASSERT_NE(io_manager.get(), nullptr);
|
||||
ASSERT_NE(io_manager->GetSkiaUnrefQueue().get(), nullptr);
|
||||
// Get io_manager directly from shell and check its existence.
|
||||
ASSERT_NE(shell->GetIOManager().get(), nullptr);
|
||||
});
|
||||
});
|
||||
|
||||
std::unique_ptr<Shell> spawn;
|
||||
|
||||
PostSync(shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell, &settings,
|
||||
&spawn] {
|
||||
auto second_configuration = RunConfiguration::InferFromSettings(settings);
|
||||
ASSERT_TRUE(second_configuration.IsValid());
|
||||
second_configuration.SetEntrypoint("emptyMain");
|
||||
const std::string initial_route("/foo");
|
||||
MockPlatformViewDelegate platform_view_delegate;
|
||||
auto child = shell->Spawn(
|
||||
std::move(second_configuration), initial_route,
|
||||
[&platform_view_delegate](Shell& shell) {
|
||||
auto result = std::make_unique<MockPlatformView>(
|
||||
platform_view_delegate, shell.GetTaskRunners());
|
||||
ON_CALL(*result, CreateRenderingSurface())
|
||||
.WillByDefault(::testing::Invoke(
|
||||
[] { return std::make_unique<MockSurface>(); }));
|
||||
return result;
|
||||
},
|
||||
[](Shell& shell) { return std::make_unique<Rasterizer>(shell); });
|
||||
spawn = std::move(child);
|
||||
});
|
||||
// Destroy the parent shell.
|
||||
DestroyShell(std::move(shell));
|
||||
|
||||
PostSync(spawn->GetTaskRunners().GetUITaskRunner(), [&spawn] {
|
||||
// We must get engine on UI thread.
|
||||
auto runtime_controller = spawn->GetEngine()->GetRuntimeController();
|
||||
PostSync(spawn->GetTaskRunners().GetIOTaskRunner(),
|
||||
[&spawn, &runtime_controller] {
|
||||
// We must get io_manager on IO thread.
|
||||
auto io_manager = runtime_controller->GetIOManager();
|
||||
// Check io_manager existence here.
|
||||
ASSERT_NE(io_manager.get(), nullptr);
|
||||
ASSERT_NE(io_manager->GetSkiaUnrefQueue().get(), nullptr);
|
||||
// Get io_manager directly from shell and check its existence.
|
||||
ASSERT_NE(spawn->GetIOManager().get(), nullptr);
|
||||
});
|
||||
});
|
||||
// Destroy the child shell.
|
||||
DestroyShell(std::move(spawn));
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, UpdateAssetResolverByTypeReplaces) {
|
||||
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
|
||||
Settings settings = CreateSettingsForFixture();
|
||||
|
||||
Reference in New Issue
Block a user