| // 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_WINDOWS_TASK_RUNNER_H_ | |
| #define FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_ | |
| #include <chrono> | |
| #include <deque> | |
| #include <functional> | |
| #include <memory> | |
| #include <mutex> | |
| #include <queue> | |
| #include <variant> | |
| #include "flutter/shell/platform/embedder/embedder.h" | |
| #include "flutter/shell/platform/windows/task_runner_window.h" | |
| namespace flutter { | |
| typedef uint64_t (*CurrentTimeProc)(); | |
| // A custom task runner that integrates with user32 GetMessage semantics so | |
| // that host app can own its own message loop and flutter still gets to process | |
| // tasks on a timely basis. | |
| class TaskRunner : public TaskRunnerWindow::Delegate { | |
| public: | |
| using TaskTimePoint = std::chrono::steady_clock::time_point; | |
| using TaskExpiredCallback = std::function<void(const FlutterTask*)>; | |
| using TaskClosure = std::function<void()>; | |
| // Creates a new task runner with the current thread, current time | |
| // provider, and callback for tasks that are ready to be run. | |
| TaskRunner(CurrentTimeProc get_current_time, | |
| const TaskExpiredCallback& on_task_expired); | |
| virtual ~TaskRunner(); | |
| // Returns `true` if the current thread is this runner's thread. | |
| virtual bool RunsTasksOnCurrentThread() const; | |
| // Post a Flutter engine task to the event loop for delayed execution. | |
| void PostFlutterTask(FlutterTask flutter_task, | |
| uint64_t flutter_target_time_nanos); | |
| // Post a task to the event loop. | |
| void PostTask(TaskClosure task); | |
| // Post a task to the event loop or run it immediately if this is being called | |
| // from the runner's thread. | |
| void RunNowOrPostTask(TaskClosure task) { | |
| if (RunsTasksOnCurrentThread()) { | |
| task(); | |
| } else { | |
| PostTask(std::move(task)); | |
| } | |
| } | |
| // |TaskRunnerWindow::Delegate| | |
| std::chrono::nanoseconds ProcessTasks(); | |
| private: | |
| typedef std::variant<FlutterTask, TaskClosure> TaskVariant; | |
| struct Task { | |
| uint64_t order; | |
| TaskTimePoint fire_time; | |
| TaskVariant variant; | |
| struct Comparer { | |
| bool operator()(const Task& a, const Task& b) { | |
| if (a.fire_time == b.fire_time) { | |
| return a.order > b.order; | |
| } | |
| return a.fire_time > b.fire_time; | |
| } | |
| }; | |
| }; | |
| // Enqueues the given task. | |
| void EnqueueTask(Task task); | |
| // Schedules timers to call `ProcessTasks()` at the runner's thread. | |
| virtual void WakeUp(); | |
| // Returns the current TaskTimePoint that can be used to determine whether a | |
| // task is expired. | |
| // | |
| // Tests can override this to mock up the time. | |
| virtual TaskTimePoint GetCurrentTimeForTask() const { | |
| return TaskTimePoint::clock::now(); | |
| } | |
| // Returns a TaskTimePoint computed from the given target time from Flutter. | |
| TaskTimePoint TimePointFromFlutterTime( | |
| uint64_t flutter_target_time_nanos) const; | |
| CurrentTimeProc get_current_time_; | |
| TaskExpiredCallback on_task_expired_; | |
| std::mutex task_queue_mutex_; | |
| std::priority_queue<Task, std::deque<Task>, Task::Comparer> task_queue_; | |
| DWORD main_thread_id_; | |
| std::shared_ptr<TaskRunnerWindow> task_runner_window_; | |
| FML_DISALLOW_COPY_AND_ASSIGN(TaskRunner); | |
| }; | |
| } // namespace flutter | |
| #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_ |