| // 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/embedder/embedder_task_runner.h" | 
 |  | 
 | #include "flutter/fml/message_loop_impl.h" | 
 | #include "flutter/fml/message_loop_task_queues.h" | 
 |  | 
 | namespace flutter { | 
 |  | 
 | EmbedderTaskRunner::EmbedderTaskRunner(DispatchTable table, | 
 |                                        size_t embedder_identifier) | 
 |     : TaskRunner(nullptr /* loop implemenation*/), | 
 |       embedder_identifier_(embedder_identifier), | 
 |       dispatch_table_(std::move(table)), | 
 |       placeholder_id_( | 
 |           fml::MessageLoopTaskQueues::GetInstance()->CreateTaskQueue()) { | 
 |   FML_DCHECK(dispatch_table_.post_task_callback); | 
 |   FML_DCHECK(dispatch_table_.runs_task_on_current_thread_callback); | 
 | } | 
 |  | 
 | EmbedderTaskRunner::~EmbedderTaskRunner() = default; | 
 |  | 
 | size_t EmbedderTaskRunner::GetEmbedderIdentifier() const { | 
 |   return embedder_identifier_; | 
 | } | 
 |  | 
 | void EmbedderTaskRunner::PostTask(const fml::closure& task) { | 
 |   PostTaskForTime(task, fml::TimePoint::Now()); | 
 | } | 
 |  | 
 | void EmbedderTaskRunner::PostTaskForTime(const fml::closure& task, | 
 |                                          fml::TimePoint target_time) { | 
 |   if (!task) { | 
 |     return; | 
 |   } | 
 |  | 
 |   uint64_t baton = 0; | 
 |  | 
 |   { | 
 |     // Release the lock before the jump via the dispatch table. | 
 |     std::scoped_lock lock(tasks_mutex_); | 
 |     baton = ++last_baton_; | 
 |     pending_tasks_[baton] = task; | 
 |   } | 
 |  | 
 |   dispatch_table_.post_task_callback(this, baton, target_time); | 
 | } | 
 |  | 
 | void EmbedderTaskRunner::PostDelayedTask(const fml::closure& task, | 
 |                                          fml::TimeDelta delay) { | 
 |   PostTaskForTime(task, fml::TimePoint::Now() + delay); | 
 | } | 
 |  | 
 | bool EmbedderTaskRunner::RunsTasksOnCurrentThread() { | 
 |   return dispatch_table_.runs_task_on_current_thread_callback(); | 
 | } | 
 |  | 
 | bool EmbedderTaskRunner::PostTask(uint64_t baton) { | 
 |   fml::closure task; | 
 |  | 
 |   { | 
 |     std::scoped_lock lock(tasks_mutex_); | 
 |     auto found = pending_tasks_.find(baton); | 
 |     if (found == pending_tasks_.end()) { | 
 |       FML_LOG(ERROR) << "Embedder attempted to post an unknown task."; | 
 |       return false; | 
 |     } | 
 |     task = found->second; | 
 |     pending_tasks_.erase(found); | 
 |  | 
 |     // Let go of the tasks mutex befor executing the task. | 
 |   } | 
 |  | 
 |   FML_DCHECK(task); | 
 |   task(); | 
 |   return true; | 
 | } | 
 |  | 
 | // |fml::TaskRunner| | 
 | fml::TaskQueueId EmbedderTaskRunner::GetTaskQueueId() { | 
 |   return placeholder_id_; | 
 | } | 
 |  | 
 | }  // namespace flutter |