Fully inplement TaskRunner for UWP (flutter/flutter#70890) (#28013)
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index b238e78..8e2f603 100755
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1754,7 +1754,9 @@
FILE: ../../../flutter/shell/platform/windows/system_utils_unittests.cc
FILE: ../../../flutter/shell/platform/windows/system_utils_win32.cc
FILE: ../../../flutter/shell/platform/windows/system_utils_winuwp.cc
+FILE: ../../../flutter/shell/platform/windows/task_runner.cc
FILE: ../../../flutter/shell/platform/windows/task_runner.h
+FILE: ../../../flutter/shell/platform/windows/task_runner_unittests.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_win32.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_win32.h
FILE: ../../../flutter/shell/platform/windows/task_runner_win32_window.cc
diff --git a/shell/platform/windows/BUILD.gn b/shell/platform/windows/BUILD.gn
index 525e852..029305e 100644
--- a/shell/platform/windows/BUILD.gn
+++ b/shell/platform/windows/BUILD.gn
@@ -77,6 +77,7 @@
"sequential_id_generator.cc",
"sequential_id_generator.h",
"system_utils.h",
+ "task_runner.cc",
"task_runner.h",
"text_input_plugin.cc",
"text_input_plugin.h",
@@ -226,6 +227,7 @@
"sequential_id_generator_unittests.cc",
"string_conversion_unittests.cc",
"system_utils_unittests.cc",
+ "task_runner_unittests.cc",
"testing/engine_modifier.h",
"testing/mock_gl_functions.h",
]
diff --git a/shell/platform/windows/flutter_windows_engine.cc b/shell/platform/windows/flutter_windows_engine.cc
index b6fb9f4..bb020d5 100644
--- a/shell/platform/windows/flutter_windows_engine.cc
+++ b/shell/platform/windows/flutter_windows_engine.cc
@@ -143,8 +143,7 @@
FlutterEngineGetProcAddresses(&embedder_api_);
task_runner_ = TaskRunner::Create(
- GetCurrentThreadId(), embedder_api_.GetCurrentTime,
- [this](const auto* task) {
+ embedder_api_.GetCurrentTime, [this](const auto* task) {
if (!engine_) {
std::cerr << "Cannot post an engine task when engine is not running."
<< std::endl;
diff --git a/shell/platform/windows/task_runner.cc b/shell/platform/windows/task_runner.cc
new file mode 100644
index 0000000..fa8b134
--- /dev/null
+++ b/shell/platform/windows/task_runner.cc
@@ -0,0 +1,104 @@
+// 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 "flutter/shell/platform/windows/task_runner.h"
+
+#include <atomic>
+#include <utility>
+
+namespace flutter {
+
+TaskRunner::TaskRunner(CurrentTimeProc get_current_time,
+ const TaskExpiredCallback& on_task_expired)
+ : get_current_time_(get_current_time),
+ on_task_expired_(std::move(on_task_expired)) {}
+
+std::chrono::nanoseconds TaskRunner::ProcessTasks() {
+ const TaskTimePoint now = TaskTimePoint::clock::now();
+
+ std::vector<Task> expired_tasks;
+
+ // Process expired tasks.
+ {
+ std::lock_guard<std::mutex> lock(task_queue_mutex_);
+ while (!task_queue_.empty()) {
+ const auto& top = task_queue_.top();
+ // If this task (and all tasks after this) has not yet expired, there is
+ // nothing more to do. Quit iterating.
+ if (top.fire_time > now) {
+ break;
+ }
+
+ // Make a record of the expired task. Do NOT service the task here
+ // because we are still holding onto the task queue mutex. We don't want
+ // other threads to block on posting tasks onto this thread till we are
+ // done processing expired tasks.
+ expired_tasks.push_back(task_queue_.top());
+
+ // Remove the tasks from the delayed tasks queue.
+ task_queue_.pop();
+ }
+ }
+
+ // Fire expired tasks.
+ {
+ // Flushing tasks here without holing onto the task queue mutex.
+ for (const auto& task : expired_tasks) {
+ if (auto flutter_task = std::get_if<FlutterTask>(&task.variant)) {
+ on_task_expired_(flutter_task);
+ } else if (auto closure = std::get_if<TaskClosure>(&task.variant))
+ (*closure)();
+ }
+ }
+
+ // Calculate duration to sleep for on next iteration.
+ {
+ std::lock_guard<std::mutex> lock(task_queue_mutex_);
+ const auto next_wake = task_queue_.empty() ? TaskTimePoint::max()
+ : task_queue_.top().fire_time;
+
+ return std::min(next_wake - now, std::chrono::nanoseconds::max());
+ }
+}
+
+TaskRunner::TaskTimePoint TaskRunner::TimePointFromFlutterTime(
+ uint64_t flutter_target_time_nanos) const {
+ const auto now = TaskTimePoint::clock::now();
+ const auto flutter_duration = flutter_target_time_nanos - get_current_time_();
+ return now + std::chrono::nanoseconds(flutter_duration);
+}
+
+void TaskRunner::PostFlutterTask(FlutterTask flutter_task,
+ uint64_t flutter_target_time_nanos) {
+ Task task;
+ task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
+ task.variant = flutter_task;
+ EnqueueTask(std::move(task));
+}
+
+void TaskRunner::PostTask(TaskClosure closure) {
+ Task task;
+ task.fire_time = TaskTimePoint::clock::now();
+ task.variant = std::move(closure);
+ EnqueueTask(std::move(task));
+}
+
+void TaskRunner::EnqueueTask(Task task) {
+ static std::atomic_uint64_t sGlobalTaskOrder(0);
+
+ task.order = ++sGlobalTaskOrder;
+ {
+ std::lock_guard<std::mutex> lock(task_queue_mutex_);
+ task_queue_.push(task);
+
+ // Make sure the queue mutex is unlocked before waking up the loop. In case
+ // the wake causes this thread to be descheduled for the primary thread to
+ // process tasks, the acquisition of the lock on that thread while holding
+ // the lock here momentarily till the end of the scope is a pessimization.
+ }
+
+ WakeUp();
+}
+
+} // namespace flutter
diff --git a/shell/platform/windows/task_runner.h b/shell/platform/windows/task_runner.h
index 0e3d444..7f181d0 100644
--- a/shell/platform/windows/task_runner.h
+++ b/shell/platform/windows/task_runner.h
@@ -5,10 +5,13 @@
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_
-#include <windows.h>
-
#include <chrono>
+#include <deque>
+#include <functional>
#include <memory>
+#include <mutex>
+#include <queue>
+#include <variant>
#include "flutter/shell/platform/embedder/embedder.h"
@@ -16,7 +19,6 @@
typedef uint64_t (*CurrentTimeProc)();
-// Abstract custom task runner for scheduling custom tasks.
class TaskRunner {
public:
using TaskTimePoint = std::chrono::steady_clock::time_point;
@@ -25,18 +27,18 @@
virtual ~TaskRunner() = default;
- // Returns if the current thread is the UI thread.
+ // Returns `true` if the current thread is this runner's thread.
virtual bool RunsTasksOnCurrentThread() const = 0;
// Post a Flutter engine task to the event loop for delayed execution.
- virtual void PostFlutterTask(FlutterTask flutter_task,
- uint64_t flutter_target_time_nanos) = 0;
+ void PostFlutterTask(FlutterTask flutter_task,
+ uint64_t flutter_target_time_nanos);
// Post a task to the event loop.
- virtual void PostTask(TaskClosure task) = 0;
+ void PostTask(TaskClosure task);
// Post a task to the event loop or run it immediately if this is being called
- // from the main thread.
+ // from the runner's thread.
void RunNowOrPostTask(TaskClosure task) {
if (RunsTasksOnCurrentThread()) {
task();
@@ -45,12 +47,57 @@
}
}
- // Creates a new task runner with the given main thread ID, current time
+ // Creates a new task runner with the current thread, current time
// provider, and callback for tasks that are ready to be run.
static std::unique_ptr<TaskRunner> Create(
- DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired);
+
+ protected:
+ TaskRunner(CurrentTimeProc get_current_time,
+ const TaskExpiredCallback& on_task_expired);
+
+ // Schedules timers to call `ProcessTasks()` at the runner's thread.
+ virtual void WakeUp() = 0;
+
+ // Executes expired task, and returns the duration until the next task
+ // deadline if exists, otherwise returns `std::chrono::nanoseconds::max()`.
+ //
+ // Each platform implementations must call this to schedule the tasks.
+ 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);
+
+ // 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_;
+
+ TaskRunner(const TaskRunner&) = delete;
+ TaskRunner& operator=(const TaskRunner&) = delete;
};
} // namespace flutter
diff --git a/shell/platform/windows/task_runner_unittests.cc b/shell/platform/windows/task_runner_unittests.cc
new file mode 100644
index 0000000..713474d
--- /dev/null
+++ b/shell/platform/windows/task_runner_unittests.cc
@@ -0,0 +1,89 @@
+// 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 <chrono>
+
+#include "flutter/fml/time/time_point.h"
+
+#include "flutter/shell/platform/windows/task_runner.h"
+
+#include "gtest/gtest.h"
+
+namespace flutter {
+namespace testing {
+
+namespace {
+class MockTaskRunner : public TaskRunner {
+ public:
+ MockTaskRunner(CurrentTimeProc get_current_time,
+ const TaskExpiredCallback& on_task_expired)
+ : TaskRunner(get_current_time, on_task_expired) {}
+
+ virtual bool RunsTasksOnCurrentThread() const override { return true; }
+
+ void SimulateTimerAwake() { ProcessTasks(); }
+
+ protected:
+ virtual void WakeUp() override {
+ // Do nothing to avoid processing tasks immediately after the tasks is
+ // posted.
+ }
+};
+
+uint64_t MockGetCurrentTime() {
+ return static_cast<uint64_t>(
+ fml::TimePoint::Now().ToEpochDelta().ToNanoseconds());
+}
+} // namespace
+
+TEST(TaskRunnerTest, MaybeExecuteTaskWithExactOrder) {
+ std::vector<uint64_t> executed_task_order;
+ auto runner =
+ MockTaskRunner(MockGetCurrentTime,
+ [&executed_task_order](const FlutterTask* expired_task) {
+ executed_task_order.push_back(expired_task->task);
+ });
+
+ uint64_t time_now = MockGetCurrentTime();
+
+ runner.PostFlutterTask(FlutterTask{nullptr, 1}, time_now);
+ runner.PostFlutterTask(FlutterTask{nullptr, 2}, time_now);
+ runner.PostTask(
+ [&executed_task_order]() { executed_task_order.push_back(3); });
+ runner.PostTask(
+ [&executed_task_order]() { executed_task_order.push_back(4); });
+
+ runner.SimulateTimerAwake();
+
+ std::vector<uint64_t> posted_task_order{1, 2, 3, 4};
+ EXPECT_EQ(executed_task_order, posted_task_order);
+}
+
+TEST(TaskRunnerTest, MaybeExecuteTaskOnlyExpired) {
+ std::set<uint64_t> executed_task;
+ auto runner = MockTaskRunner(
+ MockGetCurrentTime, [&executed_task](const FlutterTask* expired_task) {
+ executed_task.insert(expired_task->task);
+ });
+
+ uint64_t time_now = MockGetCurrentTime();
+
+ uint64_t task_expired_before_now = 1;
+ uint64_t time_before_now = time_now - 10000;
+ runner.PostFlutterTask(FlutterTask{nullptr, task_expired_before_now},
+ time_before_now);
+
+ uint64_t task_expired_after_now = 2;
+ uint64_t time_after_now = time_now + 10000;
+ runner.PostFlutterTask(FlutterTask{nullptr, task_expired_after_now},
+ time_after_now);
+
+ runner.SimulateTimerAwake();
+
+ std::set<uint64_t> only_task_expired_before_now{task_expired_before_now};
+ EXPECT_EQ(executed_task, only_task_expired_before_now);
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/shell/platform/windows/task_runner_win32.cc b/shell/platform/windows/task_runner_win32.cc
index 62de4a1..01c7179 100644
--- a/shell/platform/windows/task_runner_win32.cc
+++ b/shell/platform/windows/task_runner_win32.cc
@@ -4,27 +4,19 @@
#include "flutter/shell/platform/windows/task_runner_win32.h"
-#include <atomic>
-#include <iostream>
-#include <utility>
-
namespace flutter {
// static
std::unique_ptr<TaskRunner> TaskRunner::Create(
- DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired) {
- return std::make_unique<TaskRunnerWin32>(main_thread_id, get_current_time,
- on_task_expired);
+ return std::make_unique<TaskRunnerWin32>(get_current_time, on_task_expired);
}
-TaskRunnerWin32::TaskRunnerWin32(DWORD main_thread_id,
- CurrentTimeProc get_current_time,
+TaskRunnerWin32::TaskRunnerWin32(CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired)
- : main_thread_id_(main_thread_id),
- get_current_time_(get_current_time),
- on_task_expired_(std::move(on_task_expired)) {
+ : TaskRunner(get_current_time, on_task_expired) {
+ main_thread_id_ = GetCurrentThreadId();
task_runner_window_ = TaskRunnerWin32Window::GetSharedInstance();
task_runner_window_->AddDelegate(this);
}
@@ -38,89 +30,10 @@
}
std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() {
- const TaskTimePoint now = TaskTimePoint::clock::now();
-
- std::vector<Task> expired_tasks;
-
- // Process expired tasks.
- {
- std::lock_guard<std::mutex> lock(task_queue_mutex_);
- while (!task_queue_.empty()) {
- const auto& top = task_queue_.top();
- // If this task (and all tasks after this) has not yet expired, there is
- // nothing more to do. Quit iterating.
- if (top.fire_time > now) {
- break;
- }
-
- // Make a record of the expired task. Do NOT service the task here
- // because we are still holding onto the task queue mutex. We don't want
- // other threads to block on posting tasks onto this thread till we are
- // done processing expired tasks.
- expired_tasks.push_back(task_queue_.top());
-
- // Remove the tasks from the delayed tasks queue.
- task_queue_.pop();
- }
- }
-
- // Fire expired tasks.
- {
- // Flushing tasks here without holing onto the task queue mutex.
- for (const auto& task : expired_tasks) {
- if (auto flutter_task = std::get_if<FlutterTask>(&task.variant)) {
- on_task_expired_(flutter_task);
- } else if (auto closure = std::get_if<TaskClosure>(&task.variant))
- (*closure)();
- }
- }
-
- // Calculate duration to sleep for on next iteration.
- {
- std::lock_guard<std::mutex> lock(task_queue_mutex_);
- const auto next_wake = task_queue_.empty() ? TaskTimePoint::max()
- : task_queue_.top().fire_time;
-
- return std::min(next_wake - now, std::chrono::nanoseconds::max());
- }
+ return TaskRunner::ProcessTasks();
}
-TaskRunnerWin32::TaskTimePoint TaskRunnerWin32::TimePointFromFlutterTime(
- uint64_t flutter_target_time_nanos) const {
- const auto now = TaskTimePoint::clock::now();
- const auto flutter_duration = flutter_target_time_nanos - get_current_time_();
- return now + std::chrono::nanoseconds(flutter_duration);
-}
-
-void TaskRunnerWin32::PostFlutterTask(FlutterTask flutter_task,
- uint64_t flutter_target_time_nanos) {
- Task task;
- task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
- task.variant = flutter_task;
- EnqueueTask(std::move(task));
-}
-
-void TaskRunnerWin32::PostTask(TaskClosure closure) {
- Task task;
- task.fire_time = TaskTimePoint::clock::now();
- task.variant = std::move(closure);
- EnqueueTask(std::move(task));
-}
-
-void TaskRunnerWin32::EnqueueTask(Task task) {
- static std::atomic_uint64_t sGlobalTaskOrder(0);
-
- task.order = ++sGlobalTaskOrder;
- {
- std::lock_guard<std::mutex> lock(task_queue_mutex_);
- task_queue_.push(task);
-
- // Make sure the queue mutex is unlocked before waking up the loop. In case
- // the wake causes this thread to be descheduled for the primary thread to
- // process tasks, the acquisition of the lock on that thread while holding
- // the lock here momentarily till the end of the scope is a pessimization.
- }
-
+void TaskRunnerWin32::WakeUp() {
task_runner_window_->WakeUp();
}
diff --git a/shell/platform/windows/task_runner_win32.h b/shell/platform/windows/task_runner_win32.h
index 149e9ac..6e3ceb8 100644
--- a/shell/platform/windows/task_runner_win32.h
+++ b/shell/platform/windows/task_runner_win32.h
@@ -7,14 +7,6 @@
#include <windows.h>
-#include <chrono>
-#include <deque>
-#include <functional>
-#include <mutex>
-#include <queue>
-#include <thread>
-#include <variant>
-
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/task_runner.h"
#include "flutter/shell/platform/windows/task_runner_win32_window.h"
@@ -27,61 +19,25 @@
class TaskRunnerWin32 : public TaskRunner,
public TaskRunnerWin32Window::Delegate {
public:
- // Creates a new task runner with the given main thread ID, current time
- // provider, and callback for tasks that are ready to be run.
- TaskRunnerWin32(DWORD main_thread_id,
- CurrentTimeProc get_current_time,
+ TaskRunnerWin32(CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired);
-
virtual ~TaskRunnerWin32();
// |TaskRunner|
bool RunsTasksOnCurrentThread() const override;
- // |TaskRunner|
- void PostFlutterTask(FlutterTask flutter_task,
- uint64_t flutter_target_time_nanos) override;
-
- // |TaskRunner|
- void PostTask(TaskClosure task) override;
-
// |TaskRunnerWin32Window::Delegate|
std::chrono::nanoseconds ProcessTasks() override;
+ protected:
+ // |TaskRunner|
+ void WakeUp() override;
+
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);
-
- // Returns a TaskTimePoint computed from the given target time from Flutter.
- TaskTimePoint TimePointFromFlutterTime(
- uint64_t flutter_target_time_nanos) const;
-
DWORD main_thread_id_;
- CurrentTimeProc get_current_time_;
- TaskExpiredCallback on_task_expired_;
- std::mutex task_queue_mutex_;
- std::priority_queue<Task, std::deque<Task>, Task::Comparer> task_queue_;
std::shared_ptr<TaskRunnerWin32Window> task_runner_window_;
TaskRunnerWin32(const TaskRunnerWin32&) = delete;
-
TaskRunnerWin32& operator=(const TaskRunnerWin32&) = delete;
};
diff --git a/shell/platform/windows/task_runner_winuwp.cc b/shell/platform/windows/task_runner_winuwp.cc
index 9f8ebaf..8bba42e 100644
--- a/shell/platform/windows/task_runner_winuwp.cc
+++ b/shell/platform/windows/task_runner_winuwp.cc
@@ -4,48 +4,50 @@
#include "flutter/shell/platform/windows/task_runner_winuwp.h"
-#include <atomic>
-#include <utility>
-
namespace flutter {
// static
std::unique_ptr<TaskRunner> TaskRunner::Create(
- DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired) {
- return std::make_unique<TaskRunnerWinUwp>(main_thread_id, on_task_expired);
+ return std::make_unique<TaskRunnerWinUwp>(get_current_time, on_task_expired);
}
-TaskRunnerWinUwp::TaskRunnerWinUwp(DWORD main_thread_id,
+TaskRunnerWinUwp::TaskRunnerWinUwp(CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired)
- : main_thread_id_(main_thread_id),
- on_task_expired_(std::move(on_task_expired)) {
- dispatcher_ =
- winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher();
+ : TaskRunner(get_current_time, on_task_expired) {
+ dispatcher_queue_ =
+ winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
+ dispatcher_queue_timer_ = dispatcher_queue_.CreateTimer();
+ dispatcher_queue_timer_.Tick({this, &TaskRunnerWinUwp::OnTick});
}
TaskRunnerWinUwp::~TaskRunnerWinUwp() = default;
bool TaskRunnerWinUwp::RunsTasksOnCurrentThread() const {
- return GetCurrentThreadId() == main_thread_id_;
+ return dispatcher_queue_.HasThreadAccess();
}
-void TaskRunnerWinUwp::PostFlutterTask(FlutterTask flutter_task,
- uint64_t flutter_target_time_nanos) {
- // TODO: Handle the target time. See
- // https://github.com/flutter/flutter/issues/70890.
-
- dispatcher_.RunAsync(
- winrt::Windows::UI::Core::CoreDispatcherPriority::Normal,
- [this, flutter_task]() { on_task_expired_(&flutter_task); });
+void TaskRunnerWinUwp::WakeUp() {
+ dispatcher_queue_.TryEnqueue([this]() { ProcessTasksAndScheduleNext(); });
}
-void TaskRunnerWinUwp::PostTask(TaskClosure task) {
- // TODO: Handle the target time. See PostFlutterTask()
+void TaskRunnerWinUwp::OnTick(
+ winrt::Windows::System::DispatcherQueueTimer const&,
+ winrt::Windows::Foundation::IInspectable const&) {
+ ProcessTasks();
+}
- dispatcher_.RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal,
- [task]() { task(); });
+void TaskRunnerWinUwp::ProcessTasksAndScheduleNext() {
+ auto next = ProcessTasks();
+
+ if (next == std::chrono::nanoseconds::max()) {
+ dispatcher_queue_timer_.Stop();
+ } else {
+ dispatcher_queue_timer_.Interval(
+ std::chrono::duration_cast<winrt::Windows::Foundation::TimeSpan>(next));
+ dispatcher_queue_timer_.Start();
+ }
}
} // namespace flutter
diff --git a/shell/platform/windows/task_runner_winuwp.h b/shell/platform/windows/task_runner_winuwp.h
index 7ee6d19..d92ce80a 100644
--- a/shell/platform/windows/task_runner_winuwp.h
+++ b/shell/platform/windows/task_runner_winuwp.h
@@ -2,51 +2,44 @@
// 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_WINRT_TASK_RUNNER_H_
-#define FLUTTER_SHELL_PLATFORM_WINDOWS_WINRT_TASK_RUNNER_H_
+#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WINUWP_H_
+#define FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WINUWP_H_
-#include <windows.h>
-
-#include <third_party/cppwinrt/generated/winrt/Windows.UI.Core.h>
-
-#include <chrono>
-#include <functional>
-#include <thread>
+#include <third_party/cppwinrt/generated/winrt/Windows.Foundation.h>
+#include <third_party/cppwinrt/generated/winrt/Windows.System.h>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/task_runner.h"
namespace flutter {
-// A custom task runner that uses a CoreDispatcher to schedule
-// flutter tasks.
+// A custom task runner that uses a DispatcherQueue.
class TaskRunnerWinUwp : public TaskRunner {
public:
- TaskRunnerWinUwp(DWORD main_thread_id,
+ TaskRunnerWinUwp(CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired);
-
- ~TaskRunnerWinUwp();
-
- TaskRunnerWinUwp(const TaskRunnerWinUwp&) = delete;
- TaskRunnerWinUwp& operator=(const TaskRunnerWinUwp&) = delete;
+ virtual ~TaskRunnerWinUwp();
// |TaskRunner|
bool RunsTasksOnCurrentThread() const override;
+ protected:
// |TaskRunner|
- void PostFlutterTask(FlutterTask flutter_task,
- uint64_t flutter_target_time_nanos) override;
-
- // |TaskRunner|
- void PostTask(TaskClosure task) override;
+ void WakeUp() override;
private:
- DWORD main_thread_id_;
- TaskExpiredCallback on_task_expired_;
+ void OnTick(winrt::Windows::System::DispatcherQueueTimer const&,
+ winrt::Windows::Foundation::IInspectable const&);
- winrt::Windows::UI::Core::CoreDispatcher dispatcher_{nullptr};
+ void ProcessTasksAndScheduleNext();
+
+ winrt::Windows::System::DispatcherQueue dispatcher_queue_{nullptr};
+ winrt::Windows::System::DispatcherQueueTimer dispatcher_queue_timer_{nullptr};
+
+ TaskRunnerWinUwp(const TaskRunnerWinUwp&) = delete;
+ TaskRunnerWinUwp& operator=(const TaskRunnerWinUwp&) = delete;
};
} // namespace flutter
-#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_WINRT_TASK_RUNNER_H_
+#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WINUWP_H_