mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Embedders may use this to specify a thread whose event loop is managed by them
instead of the engine. In addition, specifying the same task runner for both
the platform and render task runners allows embedders to effectively perform
GPU rendering operations on the platform thread.
To affect this change, the following non breaking changes to the API have been
made:
* The `FlutterCustomTaskRunners` struct now has a new field `render_task_runner`
for the specification of a custom render task runner.
* The `FlutterTaskRunnerDescription` has a new field `identifier`. Embedders
must supply a unique identifier for each task runner they specify. In
addition, when describing multiple task runners that run their tasks on the
same thread, their identifiers must match.
* The embedder may need to process tasks during `FlutterEngineRun` and
`FlutterEngineShutdown`. However, the embedder doesn't have the Flutter engine
handle before `FlutterEngineRun` and is supposed to relinquish handle right
before `FlutterEngineShutdown`. Since the embedder needs the Flutter engine
handle to service tasks on other threads while these calls are underway,
there exist opportunities for deadlock. To work around this scenario, three
new calls have been added that allow more deliberate management of the Flutter
engine instance.
* `FlutterEngineRun` can be replaced with `FlutterEngineInitialize` and
`FlutterEngineRunInitialized`. The embedder can obtain a handle to the
engine after the first call but the engine will not post any tasks to custom
task runners specified by the embedder till the
`FlutterEngineRunInitialized` call. Embedders can guard the Flutter engine
handle behind a mutex for safe task runner interop.
* `FlutterEngineShutdown` can be preceded by the `FlutterEngineDeinitialize`
call. After this call the Flutter engine will no longer post tasks onto
embedder managed task runners. It is still embedder responsibility to
collect the Flutter engine handle via `FlutterEngineShutdown`.
* To maintain backwards compatibility with the old APIs, `FlutterEngineRun` is
now just a convenience for `FlutterEngineInitialize` and
`FlutterEngineRunInitilaized`. `FlutterEngineShutdown` now implicitly calls
`FlutterEngineDeinitialize` as well. This allows existing users who don't care
are custom task runner interop to keep using the old APIs.
* Adds complete test coverage for both old and new paths.
Fixes https://github.com/flutter/flutter/issues/42460
Prerequisite for https://github.com/flutter/flutter/issues/17579
105 lines
4.0 KiB
C++
105 lines
4.0 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.
|
|
|
|
#ifndef FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_TASK_RUNNER_H_
|
|
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_TASK_RUNNER_H_
|
|
|
|
#include <mutex>
|
|
#include <unordered_map>
|
|
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/synchronization/thread_annotations.h"
|
|
#include "flutter/fml/task_runner.h"
|
|
|
|
namespace flutter {
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// A task runner which delegates responsibility of task execution to an
|
|
/// embedder. This is done by managing a dispatch table to the embedder.
|
|
///
|
|
class EmbedderTaskRunner final : public fml::TaskRunner {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/// @brief A
|
|
///
|
|
struct DispatchTable {
|
|
//--------------------------------------------------------------------------
|
|
/// Delegates responsibility of deferred task execution to the embedder.
|
|
/// Once the embedder gets the task, it must call
|
|
/// `EmbedderTaskRunner::PostTask` with the supplied `task_baton` on the
|
|
/// correct thread after the tasks `target_time` point expires.
|
|
///
|
|
std::function<void(EmbedderTaskRunner* task_runner,
|
|
uint64_t task_baton,
|
|
fml::TimePoint target_time)>
|
|
post_task_callback;
|
|
//--------------------------------------------------------------------------
|
|
/// Asks the embedder if tasks posted to it on this task task runner via the
|
|
/// `post_task_callback` will be executed (after task expiry) on the calling
|
|
/// thread.
|
|
///
|
|
std::function<bool(void)> runs_task_on_current_thread_callback;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Create a task runner with a dispatch table for delegation of
|
|
/// task runner responsibility to the embedder. When embedders
|
|
/// specify task runner dispatch tables that service tasks on the
|
|
/// same thread, they also must ensure that their
|
|
/// `embedder_idetifier`s match. This allows the engine to
|
|
/// determine task runner equality without actually posting tasks
|
|
/// to the task runner.
|
|
///
|
|
/// @param[in] table The task runner dispatch table.
|
|
/// @param[in] embedder_identifier The embedder identifier
|
|
///
|
|
EmbedderTaskRunner(DispatchTable table, size_t embedder_identifier);
|
|
|
|
// |fml::TaskRunner|
|
|
~EmbedderTaskRunner() override;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief The unique identifier provided by the embedder for the task
|
|
/// runner. Embedders whose dispatch tables service tasks on the
|
|
/// same underlying OS thread must ensure that their identifiers
|
|
/// match. This allows the engine to determine task runner
|
|
/// equality without posting tasks on the thread.
|
|
///
|
|
/// @return The embedder identifier.
|
|
///
|
|
size_t GetEmbedderIdentifier() const;
|
|
|
|
bool PostTask(uint64_t baton);
|
|
|
|
private:
|
|
const size_t embedder_identifier_;
|
|
DispatchTable dispatch_table_;
|
|
std::mutex tasks_mutex_;
|
|
uint64_t last_baton_ FML_GUARDED_BY(tasks_mutex_);
|
|
std::unordered_map<uint64_t, fml::closure> pending_tasks_
|
|
FML_GUARDED_BY(tasks_mutex_);
|
|
fml::TaskQueueId placeholder_id_;
|
|
|
|
// |fml::TaskRunner|
|
|
void PostTask(fml::closure task) override;
|
|
|
|
// |fml::TaskRunner|
|
|
void PostTaskForTime(fml::closure task, fml::TimePoint target_time) override;
|
|
|
|
// |fml::TaskRunner|
|
|
void PostDelayedTask(fml::closure task, fml::TimeDelta delay) override;
|
|
|
|
// |fml::TaskRunner|
|
|
bool RunsTasksOnCurrentThread() override;
|
|
|
|
// |fml::TaskRunner|
|
|
fml::TaskQueueId GetTaskQueueId() override;
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(EmbedderTaskRunner);
|
|
};
|
|
|
|
} // namespace flutter
|
|
|
|
#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_TASK_RUNNER_H_
|