Skip to content

Commit

Permalink
Share the io_manager between parent and spawn engine (flutter#29915)
Browse files Browse the repository at this point in the history
  • Loading branch information
eggfly authored Dec 1, 2021
1 parent 8ac9366 commit 5ad06c2
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 24 deletions.
12 changes: 10 additions & 2 deletions runtime/runtime_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_, //
Expand All @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion runtime/runtime_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 10 additions & 3 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(
Expand All @@ -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;
Expand All @@ -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();
}
Expand Down
6 changes: 5 additions & 1 deletion shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions shell/common/engine_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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());
});
Expand All @@ -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());
});
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 23 additions & 11 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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), //
Expand All @@ -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,
Expand Down Expand Up @@ -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();
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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), //
Expand All @@ -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), //
Expand Down Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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();
Expand Down
6 changes: 4 additions & 2 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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();

Expand Down
101 changes: 101 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 5ad06c2

Please sign in to comment.