Replace flutter_runner::Thread with fml::Thread. (flutter/engine#26193)

This commit is contained in:
Hunter Freyer 2021-06-03 17:39:04 -04:00 committed by GitHub
parent 5bf41ddae1
commit 84d62201b6
19 changed files with 150 additions and 323 deletions

View File

@ -229,6 +229,8 @@ FILE: ../../../flutter/fml/platform/darwin/string_range_sanitization_unittests.m
FILE: ../../../flutter/fml/platform/fuchsia/message_loop_fuchsia.cc
FILE: ../../../flutter/fml/platform/fuchsia/message_loop_fuchsia.h
FILE: ../../../flutter/fml/platform/fuchsia/paths_fuchsia.cc
FILE: ../../../flutter/fml/platform/fuchsia/task_observers.cc
FILE: ../../../flutter/fml/platform/fuchsia/task_observers.h
FILE: ../../../flutter/fml/platform/linux/message_loop_linux.cc
FILE: ../../../flutter/fml/platform/linux/message_loop_linux.h
FILE: ../../../flutter/fml/platform/linux/paths_linux.cc
@ -1360,8 +1362,6 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/keyboard.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/keyboard.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/keyboard_unittest.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/logging.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/loop.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/loop.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/main.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/aot_product_runtime
FILE: ../../../flutter/shell/platform/fuchsia/flutter/meta/aot_runtime
@ -1383,12 +1383,8 @@ FILE: ../../../flutter/shell/platform/fuchsia/flutter/runner_tzdata_unittest.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/runner_unittest.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/surface.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/surface.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/task_observers.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/task_observers.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/task_runner_adapter.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/task_runner_adapter.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/thread.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/thread.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/unique_fdio_ns.h
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.cc
FILE: ../../../flutter/shell/platform/fuchsia/flutter/vsync_waiter.h

View File

@ -180,6 +180,8 @@ source_set("fml") {
"platform/fuchsia/message_loop_fuchsia.cc",
"platform/fuchsia/message_loop_fuchsia.h",
"platform/fuchsia/paths_fuchsia.cc",
"platform/fuchsia/task_observers.cc",
"platform/fuchsia/task_observers.h",
]
public_deps += [

View File

@ -8,11 +8,25 @@
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/zx/time.h>
#include "flutter/fml/platform/fuchsia/task_observers.h"
namespace fml {
MessageLoopFuchsia::MessageLoopFuchsia()
: loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
namespace {
// See comment on `ExecuteAfterTaskObservers` for explanation.
static void LoopEpilogue(async_loop_t*, void*) {
ExecuteAfterTaskObservers();
}
constexpr async_loop_config_t kLoopConfig = {
.make_default_for_current_thread = false,
.epilogue = &LoopEpilogue,
};
} // namespace
MessageLoopFuchsia::MessageLoopFuchsia() : loop_(&kLoopConfig) {
async_set_default_dispatcher(loop_.dispatcher());
}

View File

@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "task_observers.h"
#include "flutter/fml/platform/fuchsia/task_observers.h"
#include <map>
namespace flutter_runner {
namespace fml {
thread_local std::map<intptr_t, fit::closure> tTaskObservers;
@ -27,4 +27,4 @@ void CurrentMessageLoopRemoveAfterTaskObserver(intptr_t key) {
tTaskObservers.erase(key);
}
} // namespace flutter_runner
} // namespace fml

View File

@ -0,0 +1,40 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_
#include <lib/fit/function.h>
namespace fml {
// Executes all closures that were registered via
// `CurrentMessageLoopAddAfterTaskObserver` on this thread.
//
// WARNING(fxbug.dev/77957): These task observers are distinct from the task
// observers that can be specified via `fml::MessageLoop::AddTaskObserver` and
// they behave differently!
//
// Task observers registered via `fml::MessageLoop::AddTaskObserver` only fire
// after work that was posted via the `fml::MessageLoop`'s `TaskRunner`
// completes. Work that is posted directly to the Fuchsia message loop (e.g.
// using `async::PostTask(async_get_default_dispatcher(), ...)`) is invisible to
// `fml::MessageLoop`, so the `fml::MessageLoop`'s task observers don't fire.
//
// The task observers registered with `CurrentMessageLoopAddAfterTaskObserver`,
// however, fire after _every_ work item is completed, regardless of whether it
// was posted to the Fuchsia message loop directly or via `fml::MessageLoop`.
//
// These two mechanisms are redundant and confusing, so we should fix it
// somehow.
void ExecuteAfterTaskObservers();
void CurrentMessageLoopAddAfterTaskObserver(intptr_t key,
fit::closure observer);
void CurrentMessageLoopRemoveAfterTaskObserver(intptr_t key);
} // namespace fml
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_

View File

@ -68,20 +68,14 @@ template("runner_sources") {
"keyboard.cc",
"keyboard.h",
"logging.h",
"loop.cc",
"loop.h",
"platform_view.cc",
"platform_view.h",
"runner.cc",
"runner.h",
"surface.cc",
"surface.h",
"task_observers.cc",
"task_observers.h",
"task_runner_adapter.cc",
"task_runner_adapter.h",
"thread.cc",
"thread.h",
"unique_fdio_ns.h",
"vsync_waiter.cc",
"vsync_waiter.h",

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define FML_USED_ON_EMBEDDER
#include "component.h"
#include <dlfcn.h>
@ -27,6 +29,7 @@
#include <sstream>
#include "flutter/fml/mapping.h"
#include "flutter/fml/platform/fuchsia/task_observers.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/unique_fd.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
@ -37,9 +40,6 @@
#include "runtime/dart/utils/tempfs.h"
#include "runtime/dart/utils/vmo.h"
#include "task_observers.h"
#include "task_runner_adapter.h"
// TODO(kaushikiska): Use these constants from ::llcpp::fuchsia::io
// Can read from target object.
constexpr uint32_t OPEN_RIGHT_READABLE = 1u;
@ -186,11 +186,11 @@ ActiveApplication Application::Create(
fuchsia::sys::StartupInfo startup_info,
std::shared_ptr<sys::ServiceDirectory> runner_incoming_services,
fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
std::unique_ptr<Thread> thread = std::make_unique<Thread>();
auto thread = std::make_unique<fml::Thread>();
std::unique_ptr<Application> application;
fml::AutoResetWaitableEvent latch;
async::PostTask(thread->dispatcher(), [&]() mutable {
thread->GetTaskRunner()->PostTask([&]() mutable {
application.reset(
new Application(std::move(termination_callback), std::move(package),
std::move(startup_info), runner_incoming_services,
@ -199,7 +199,8 @@ ActiveApplication Application::Create(
});
latch.Wait();
return {.thread = std::move(thread), .application = std::move(application)};
return {.platform_thread = std::move(thread),
.application = std::move(application)};
}
Application::Application(
@ -491,11 +492,11 @@ Application::Application(
settings_.leak_vm = false;
settings_.task_observer_add =
std::bind(&CurrentMessageLoopAddAfterTaskObserver, std::placeholders::_1,
std::placeholders::_2);
std::bind(&fml::CurrentMessageLoopAddAfterTaskObserver,
std::placeholders::_1, std::placeholders::_2);
settings_.task_observer_remove = std::bind(
&CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
&fml::CurrentMessageLoopRemoveAfterTaskObserver, std::placeholders::_1);
settings_.log_message_callback = [](const std::string& tag,
const std::string& message) {
@ -517,8 +518,7 @@ Application::Application(
#endif // defined(__aarch64__)
auto weak_application = weak_factory_.GetWeakPtr();
auto platform_task_runner =
CreateFMLTaskRunner(async_get_default_dispatcher());
auto platform_task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
const std::string component_url = package.resolved_url;
settings_.unhandled_exception_callback = [weak_application,
platform_task_runner,

View File

@ -26,7 +26,6 @@
#include "engine.h"
#include "flutter_runner_product_configuration.h"
#include "thread.h"
#include "unique_fdio_ns.h"
namespace flutter_runner {
@ -34,12 +33,12 @@ namespace flutter_runner {
class Application;
struct ActiveApplication {
std::unique_ptr<Thread> thread;
std::unique_ptr<fml::Thread> platform_thread;
std::unique_ptr<Application> application;
ActiveApplication& operator=(ActiveApplication&& other) noexcept {
if (this != &other) {
this->thread.reset(other.thread.release());
this->platform_thread.reset(other.platform_thread.release());
this->application.reset(other.application.release());
}
return *this;

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define FML_USED_ON_EMBEDDER
#include "engine.h"
#include <lib/async/cpp/task.h>
@ -10,6 +12,7 @@
#include "flutter/common/graphics/persistent_cache.h"
#include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/message_loop.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/task_runner.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
@ -24,7 +27,6 @@
#include "fuchsia_intl.h"
#include "platform_view.h"
#include "surface.h"
#include "task_runner_adapter.h"
#include "vsync_waiter.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
@ -80,12 +82,15 @@ Engine::Engine(Delegate& delegate,
// Get the task runners from the managed threads. The current thread will be
// used as the "platform" thread.
fml::RefPtr<fml::TaskRunner> platform_task_runner =
fml::MessageLoop::GetCurrent().GetTaskRunner();
const flutter::TaskRunners task_runners(
thread_label_, // Dart thread labels
CreateFMLTaskRunner(async_get_default_dispatcher()), // platform
CreateFMLTaskRunner(threads_[0].dispatcher()), // raster
CreateFMLTaskRunner(threads_[1].dispatcher()), // ui
CreateFMLTaskRunner(threads_[2].dispatcher()) // io
thread_label_, // Dart thread labels
platform_task_runner, // platform
threads_[0].GetTaskRunner(), // raster
threads_[1].GetTaskRunner(), // ui
threads_[2].GetTaskRunner() // io
);
UpdateNativeThreadLabelNames(thread_label_, task_runners);
@ -120,10 +125,9 @@ Engine::Engine(Delegate& delegate,
// This handles the fidl error callback when the Session connection is
// broken. The SessionListener interface also has an OnError method, which is
// invoked on the platform thread (in PlatformView).
fml::closure session_error_callback = [dispatcher =
async_get_default_dispatcher(),
fml::closure session_error_callback = [task_runner = platform_task_runner,
weak = weak_factory_.GetWeakPtr()]() {
async::PostTask(dispatcher, [weak]() {
task_runner->PostTask([weak]() {
if (weak) {
weak->Terminate();
}
@ -221,9 +225,9 @@ Engine::Engine(Delegate& delegate,
// platform thread when that happens. The Session itself should also be
// disconnected when this happens, and it will also attempt to terminate.
fit::closure on_session_listener_error_callback =
[dispatcher = async_get_default_dispatcher(),
[task_runner = platform_task_runner,
weak = weak_factory_.GetWeakPtr()]() {
async::PostTask(dispatcher, [weak]() {
task_runner->PostTask([weak]() {
if (weak) {
weak->Terminate();
}
@ -511,9 +515,6 @@ Engine::Engine(Delegate& delegate,
Engine::~Engine() {
shell_.reset();
for (auto& thread : threads_) {
thread.Quit();
}
for (auto& thread : threads_) {
thread.Join();
}

View File

@ -27,7 +27,6 @@
#include "flutter_runner_product_configuration.h"
#include "fuchsia_external_view_embedder.h"
#include "isolate_configurator.h"
#include "thread.h"
#include "vulkan_surface_producer.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
@ -73,7 +72,7 @@ class Engine final {
Delegate& delegate_;
const std::string thread_label_;
std::array<Thread, 3> threads_;
std::array<fml::Thread, 3> threads_;
std::shared_ptr<DefaultSessionConnection> session_connection_;
std::optional<VulkanSurfaceProducer> surface_producer_;

View File

@ -8,7 +8,6 @@
#include <string>
#include <vector>
#include "loop.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"

View File

@ -1,47 +0,0 @@
// 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.
#include "loop.h"
#include <lib/async-loop/loop.h>
#include <lib/async/default.h>
#include "task_observers.h"
namespace flutter_runner {
namespace {
static void LoopEpilogue(async_loop_t*, void*) {
ExecuteAfterTaskObservers();
}
constexpr async_loop_config_t kAttachedLoopConfig = {
.default_accessors =
{
.getter = async_get_default_dispatcher,
.setter = async_set_default_dispatcher,
},
.make_default_for_current_thread = true,
.epilogue = &LoopEpilogue,
};
constexpr async_loop_config_t kDetachedLoopConfig = {
.default_accessors =
{
.getter = async_get_default_dispatcher,
.setter = async_set_default_dispatcher,
},
.make_default_for_current_thread = false,
.epilogue = &LoopEpilogue,
};
} // namespace
async::Loop* MakeObservableLoop(bool attachToThread) {
return new async::Loop(
&(attachToThread ? kAttachedLoopConfig : kDetachedLoopConfig));
}
} // namespace flutter_runner

View File

@ -1,17 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_LOOP_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_LOOP_H_
#include <lib/async-loop/cpp/loop.h>
namespace flutter_runner {
// Creates a loop which allows task observers to be attached to it.
async::Loop* MakeObservableLoop(bool attachToThread);
} // namespace flutter_runner
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_LOOP_H_

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define FML_USED_ON_EMBEDDER
#include <lib/async-loop/cpp/loop.h>
#include <lib/sys/inspect/cpp/component.h>
#include <lib/trace-provider/provider.h>
@ -9,7 +11,8 @@
#include <cstdlib>
#include "loop.h"
#include "fml/message_loop.h"
#include "lib/async/default.h"
#include "platform/utils.h"
#include "runner.h"
#include "runtime/dart/utils/build_info.h"
@ -17,7 +20,7 @@
#include "runtime/dart/utils/tempfs.h"
int main(int argc, char const* argv[]) {
std::unique_ptr<async::Loop> loop(flutter_runner::MakeObservableLoop(true));
fml::MessageLoop::EnsureInitializedForCurrentThread();
// Create our component context which is served later.
auto context = sys::ComponentContext::Create();
@ -35,7 +38,8 @@ int main(int argc, char const* argv[]) {
bool already_started;
// Use CreateSynchronously to prevent loss of early events.
trace::TraceProviderWithFdio::CreateSynchronously(
loop->dispatcher(), "flutter_runner", &provider, &already_started);
async_get_default_dispatcher(), "flutter_runner", &provider,
&already_started);
}
// Set up the process-wide /tmp memfs.
@ -43,12 +47,13 @@ int main(int argc, char const* argv[]) {
FML_DLOG(INFO) << "Flutter application services initialized.";
flutter_runner::Runner runner(loop.get(), context.get());
fml::MessageLoop& loop = fml::MessageLoop::GetCurrent();
flutter_runner::Runner runner(loop.GetTaskRunner(), context.get());
// Wait to serve until we have finished all of our setup.
context->outgoing()->ServeFromStartupInfo();
loop->Run();
loop.Run();
FML_DLOG(INFO) << "Flutter application services terminated.";
return EXIT_SUCCESS;

View File

@ -19,6 +19,7 @@
#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/text/font_collection.h"
#include "flutter/runtime/dart_vm.h"
#include "lib/async/default.h"
#include "lib/sys/cpp/component_context.h"
#include "runtime/dart/utils/files.h"
#include "runtime/dart/utils/root_inspect_node.h"
@ -148,8 +149,9 @@ static void RegisterProfilerSymbols(const char* symbols_path,
}
#endif // !defined(DART_PRODUCT)
Runner::Runner(async::Loop* loop, sys::ComponentContext* context)
: loop_(loop), context_(context) {
Runner::Runner(fml::RefPtr<fml::TaskRunner> task_runner,
sys::ComponentContext* context)
: task_runner_(task_runner), context_(context) {
#if !defined(DART_PRODUCT)
// The VM service isolate uses the process-wide namespace. It writes the
// vm service protocol port under /tmp. The VMServiceObject exposes that
@ -232,12 +234,11 @@ void Runner::StartComponent(
// there being multiple application runner instance in the process at the same
// time. So it is safe to use the raw pointer.
Application::TerminationCallback termination_callback =
[task_runner = loop_->dispatcher(), //
application_runner = this //
](const Application* application) {
async::PostTask(task_runner, [application_runner, application]() {
application_runner->OnApplicationTerminate(application);
});
[application_runner = this](const Application* application) {
application_runner->task_runner_->PostTask(
[application_runner, application]() {
application_runner->OnApplicationTerminate(application);
});
};
auto active_application = Application::Create(
@ -266,21 +267,17 @@ void Runner::OnApplicationTerminate(const Application* application) {
// Grab the items out of the entry because we will have to rethread the
// destruction.
auto application_to_destroy = std::move(active_application.application);
auto application_thread = std::move(active_application.thread);
auto application_thread = std::move(active_application.platform_thread);
// Delegate the entry.
active_applications_.erase(application);
// Post the task to destroy the application and quit its message loop.
async::PostTask(
application_thread->dispatcher(),
fml::MakeCopyable([instance = std::move(application_to_destroy),
thread = application_thread.get()]() mutable {
instance.reset();
thread->Quit();
}));
application_thread->GetTaskRunner()->PostTask(fml::MakeCopyable(
[instance = std::move(application_to_destroy),
thread = application_thread.get()]() mutable { instance.reset(); }));
// This works because just posted the quit task on the hosted thread.
// Terminate and join the thread's message loop.
application_thread->Join();
}
@ -304,27 +301,36 @@ bool Runner::SetupTZDataInternal() {
#if !defined(DART_PRODUCT)
void Runner::SetupTraceObserver() {
trace_observer_ = std::make_unique<trace::TraceObserver>();
trace_observer_->Start(loop_->dispatcher(), [runner = this]() {
if (!trace_is_category_enabled("dart:profiler")) {
return;
}
if (trace_state() == TRACE_STARTED) {
runner->prolonged_context_ = trace_acquire_prolonged_context();
Dart_StartProfiling();
} else if (trace_state() == TRACE_STOPPING) {
for (auto& it : runner->active_applications_) {
fml::AutoResetWaitableEvent latch;
async::PostTask(it.second.thread->dispatcher(), [&]() {
it.second.application->WriteProfileToTrace();
latch.Signal();
});
latch.Wait();
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(task_runner_, [&]() {
// Running this initialization code on task_runner_ ensures that the call to
// `async_get_default_dispatcher()` will capture the correct dispatcher.
trace_observer_ = std::make_unique<trace::TraceObserver>();
trace_observer_->Start(async_get_default_dispatcher(), [runner = this]() {
if (!trace_is_category_enabled("dart:profiler")) {
return;
}
Dart_StopProfiling();
trace_release_prolonged_context(runner->prolonged_context_);
}
if (trace_state() == TRACE_STARTED) {
runner->prolonged_context_ = trace_acquire_prolonged_context();
Dart_StartProfiling();
} else if (trace_state() == TRACE_STOPPING) {
for (auto& it : runner->active_applications_) {
fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(
it.second.platform_thread->GetTaskRunner(), [&]() {
it.second.application->WriteProfileToTrace();
latch.Signal();
});
latch.Wait();
}
Dart_StopProfiling();
trace_release_prolonged_context(runner->prolonged_context_);
}
});
latch.Signal();
});
latch.Wait();
}
#endif // !defined(DART_PRODUCT)

View File

@ -16,6 +16,8 @@
#include "component.h"
#include "flutter/fml/macros.h"
#include "fml/memory/ref_ptr.h"
#include "fml/task_runner.h"
#include "lib/fidl/cpp/binding_set.h"
#include "runtime/dart/utils/vmservice_object.h"
@ -25,13 +27,14 @@ namespace flutter_runner {
// their own threads.
class Runner final : public fuchsia::sys::Runner {
public:
// Does not take ownership of loop or context.
Runner(async::Loop* loop, sys::ComponentContext* context);
// Does not take ownership of context.
Runner(fml::RefPtr<fml::TaskRunner> task_runner,
sys::ComponentContext* context);
~Runner();
private:
async::Loop* loop_;
fml::RefPtr<fml::TaskRunner> task_runner_;
sys::ComponentContext* context_;
fidl::BindingSet<fuchsia::sys::Runner> active_applications_bindings_;

View File

@ -1,21 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_
#include <lib/fit/function.h>
namespace flutter_runner {
void ExecuteAfterTaskObservers();
void CurrentMessageLoopAddAfterTaskObserver(intptr_t key,
fit::closure observer);
void CurrentMessageLoopRemoveAfterTaskObserver(intptr_t key);
} // namespace flutter_runner
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_TASK_OBSERVERS_H_

View File

@ -1,102 +0,0 @@
// 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.
#include "thread.h"
#include <lib/async-loop/cpp/loop.h>
#include <unistd.h>
#include <algorithm>
#include <climits>
#include "flutter/fml/logging.h"
#include "loop.h"
namespace flutter_runner {
typedef void (*ThreadEntry)(Thread*);
namespace {
size_t NextPageSizeMultiple(size_t size) {
const size_t page_size = sysconf(_SC_PAGE_SIZE);
FML_CHECK(page_size != 0);
size = std::max<size_t>(size, page_size);
size_t rem = size % page_size;
if (rem == 0) {
return size;
}
return size + page_size - rem;
}
bool CreateThread(pthread_t* thread,
ThreadEntry main,
Thread* argument,
size_t stack_size) {
pthread_attr_t thread_attributes;
if (pthread_attr_init(&thread_attributes) != 0) {
return false;
}
stack_size = std::max<size_t>(NextPageSizeMultiple(PTHREAD_STACK_MIN),
NextPageSizeMultiple(stack_size));
if (pthread_attr_setstacksize(&thread_attributes, stack_size) != 0) {
return false;
}
auto result =
pthread_create(thread, &thread_attributes,
reinterpret_cast<void* (*)(void*)>(main), argument);
pthread_attr_destroy(&thread_attributes);
return result == 0;
}
} // anonymous namespace
Thread::Thread() {
loop_.reset(MakeObservableLoop(false));
valid_ = CreateThread(
&thread_, [](Thread* thread) { thread->Main(); }, this, 1 << 20);
}
Thread::~Thread() {
Join();
}
bool Thread::IsValid() const {
return valid_;
}
async_dispatcher_t* Thread::dispatcher() const {
return loop_->dispatcher();
}
void Thread::Main() {
async_set_default_dispatcher(loop_->dispatcher());
loop_->Run();
}
void Thread::Quit() {
loop_->Quit();
}
bool Thread::Join() {
if (!valid_) {
return false;
}
bool result = pthread_join(thread_, nullptr) == 0;
valid_ = false;
return result;
}
} // namespace flutter_runner

View File

@ -1,44 +0,0 @@
// 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.
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_THREAD_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_THREAD_H_
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/default.h>
#include <pthread.h>
#include <functional>
#include "flutter/fml/macros.h"
namespace flutter_runner {
class Thread {
public:
Thread();
~Thread();
void Quit();
bool Join();
bool IsValid() const;
async_dispatcher_t* dispatcher() const;
private:
bool valid_;
pthread_t thread_;
std::unique_ptr<async::Loop> loop_;
void Main();
FML_DISALLOW_COPY_AND_ASSIGN(Thread);
};
} // namespace flutter_runner
#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_THREAD_H_