flutter_flutter/shell/platform/embedder/embedder_thread_host.cc
Chinmay Garde eec74e5c92
Rename the blink namespace to flutter. (#8517)
Some components in the Flutter engine were derived from the forked blink codebase. While the forked components have either been removed or rewritten, the use of the blink namespace has mostly (and inconsistently) remained. This renames the blink namesapce to flutter for consistency. There are no functional changes in this patch.
2019-04-09 12:44:42 -07:00

207 lines
6.6 KiB
C++

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is why we can't yet export the UI thread to embedders.
#define FML_USED_ON_EMBEDDER
#include "flutter/shell/platform/embedder/embedder_thread_host.h"
#include "flutter/fml/message_loop.h"
#include "flutter/shell/platform/embedder/embedder_safe_access.h"
namespace shell {
static fml::RefPtr<EmbedderTaskRunner> CreateEmbedderTaskRunner(
const FlutterTaskRunnerDescription* description) {
if (description == nullptr) {
return {};
}
if (SAFE_ACCESS(description, runs_task_on_current_thread_callback, nullptr) ==
nullptr) {
FML_LOG(ERROR) << "FlutterTaskRunnerDescription.runs_task_on_current_"
"thread_callback was nullptr.";
return {};
}
if (SAFE_ACCESS(description, post_task_callback, nullptr) == nullptr) {
FML_LOG(ERROR)
<< "FlutterTaskRunnerDescription.post_task_callback was nullptr.";
return {};
}
auto user_data = SAFE_ACCESS(description, user_data, nullptr);
// ABI safety checks have been completed.
auto post_task_callback_c = description->post_task_callback;
auto runs_task_on_current_thread_callback_c =
description->runs_task_on_current_thread_callback;
EmbedderTaskRunner::DispatchTable task_runner_dispatch_table = {
// .post_task_callback
[post_task_callback_c, user_data](EmbedderTaskRunner* task_runner,
uint64_t task_baton,
fml::TimePoint target_time) -> void {
FlutterTask task = {
// runner
reinterpret_cast<FlutterTaskRunner>(task_runner),
// task
task_baton,
};
post_task_callback_c(task, target_time.ToEpochDelta().ToNanoseconds(),
user_data);
},
// runs_task_on_current_thread_callback
[runs_task_on_current_thread_callback_c, user_data]() -> bool {
return runs_task_on_current_thread_callback_c(user_data);
}};
return fml::MakeRefCounted<EmbedderTaskRunner>(task_runner_dispatch_table);
}
std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners) {
{
auto host = CreateEmbedderManagedThreadHost(custom_task_runners);
if (host && host->IsValid()) {
return host;
}
}
// Only attempt to create the engine managed host if the embedder did not
// specify a custom configuration. We don't want to fallback to the engine
// managed configuration if the embedder attempted to specify a configuration
// but messed up with an incorrect configuration.
if (custom_task_runners == nullptr) {
auto host = CreateEngineManagedThreadHost();
if (host && host->IsValid()) {
return host;
}
}
return nullptr;
}
constexpr const char* kFlutterThreadName = "io.flutter";
// static
std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEmbedderManagedThreadHost(
const FlutterCustomTaskRunners* custom_task_runners) {
if (custom_task_runners == nullptr) {
return nullptr;
}
const auto platform_task_runner = CreateEmbedderTaskRunner(
SAFE_ACCESS(custom_task_runners, platform_task_runner, nullptr));
// TODO(chinmaygarde): Add more here as we allow more threads to be controlled
// by the embedder. Create fallbacks as necessary.
if (!platform_task_runner) {
return nullptr;
}
ThreadHost thread_host(kFlutterThreadName, ThreadHost::Type::GPU |
ThreadHost::Type::IO |
ThreadHost::Type::UI);
flutter::TaskRunners task_runners(
kFlutterThreadName,
platform_task_runner, // platform
thread_host.gpu_thread->GetTaskRunner(), // gpu
thread_host.ui_thread->GetTaskRunner(), // ui
thread_host.io_thread->GetTaskRunner() // io
);
if (!task_runners.IsValid()) {
return nullptr;
}
std::set<fml::RefPtr<EmbedderTaskRunner>> embedder_task_runners;
embedder_task_runners.insert(platform_task_runner);
auto embedder_host = std::make_unique<EmbedderThreadHost>(
std::move(thread_host), std::move(task_runners),
std::move(embedder_task_runners));
if (embedder_host->IsValid()) {
return embedder_host;
}
return nullptr;
}
// static
std::unique_ptr<EmbedderThreadHost>
EmbedderThreadHost::CreateEngineManagedThreadHost() {
// Create a thread host with the current thread as the platform thread and all
// other threads managed.
ThreadHost thread_host(kFlutterThreadName, ThreadHost::Type::GPU |
ThreadHost::Type::IO |
ThreadHost::Type::UI);
fml::MessageLoop::EnsureInitializedForCurrentThread();
// For embedder platforms that don't have native message loop interop, this
// will reference a task runner that points to a null message loop
// implementation.
auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
flutter::TaskRunners task_runners(
kFlutterThreadName,
platform_task_runner, // platform
thread_host.gpu_thread->GetTaskRunner(), // gpu
thread_host.ui_thread->GetTaskRunner(), // ui
thread_host.io_thread->GetTaskRunner() // io
);
if (!task_runners.IsValid()) {
return nullptr;
}
std::set<fml::RefPtr<EmbedderTaskRunner>> empty_embedder_task_runners;
auto embedder_host = std::make_unique<EmbedderThreadHost>(
std::move(thread_host), std::move(task_runners),
empty_embedder_task_runners);
if (embedder_host->IsValid()) {
return embedder_host;
}
return nullptr;
}
EmbedderThreadHost::EmbedderThreadHost(
ThreadHost host,
flutter::TaskRunners runners,
std::set<fml::RefPtr<EmbedderTaskRunner>> embedder_task_runners)
: host_(std::move(host)), runners_(std::move(runners)) {
for (const auto& runner : embedder_task_runners) {
runners_map_[reinterpret_cast<int64_t>(runner.get())] = runner;
}
}
EmbedderThreadHost::~EmbedderThreadHost() = default;
bool EmbedderThreadHost::IsValid() const {
return runners_.IsValid();
}
const flutter::TaskRunners& EmbedderThreadHost::GetTaskRunners() const {
return runners_;
}
bool EmbedderThreadHost::PostTask(int64_t runner, uint64_t task) const {
auto found = runners_map_.find(runner);
if (found == runners_map_.end()) {
return false;
}
return found->second->PostTask(task);
}
} // namespace shell