mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
fe7e444d6f
* Refactor to move Task Queue to its own class - This is to help with sharing task queue among multiple message loops going forward. - currently there is 1:1 mapping between task queue and message loop, we are still maintaining the semantics for this change. * Add mutex include * Add unit tests for task queue * fix formatting * license
98 lines
2.9 KiB
C++
98 lines
2.9 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.
|
|
|
|
#define FML_USED_ON_EMBEDDER
|
|
|
|
#include "flutter/fml/message_loop_task_queue.h"
|
|
|
|
namespace fml {
|
|
|
|
MessageLoopTaskQueue::MessageLoopTaskQueue() : order_(0) {}
|
|
|
|
MessageLoopTaskQueue::~MessageLoopTaskQueue() = default;
|
|
|
|
void MessageLoopTaskQueue::Dispose() {
|
|
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
|
|
delayed_tasks_ = {};
|
|
}
|
|
|
|
fml::TimePoint MessageLoopTaskQueue::RegisterTask(fml::closure task,
|
|
fml::TimePoint target_time) {
|
|
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
|
|
delayed_tasks_.push({++order_, std::move(task), target_time});
|
|
return delayed_tasks_.top().GetTargetTime();
|
|
}
|
|
|
|
bool MessageLoopTaskQueue::HasPendingTasks() {
|
|
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
|
|
return !delayed_tasks_.empty();
|
|
}
|
|
|
|
fml::TimePoint MessageLoopTaskQueue::GetTasksToRunNow(
|
|
FlushType type,
|
|
std::vector<fml::closure>& invocations) {
|
|
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
|
|
|
|
const auto now = fml::TimePoint::Now();
|
|
while (!delayed_tasks_.empty()) {
|
|
const auto& top = delayed_tasks_.top();
|
|
if (top.GetTargetTime() > now) {
|
|
break;
|
|
}
|
|
invocations.emplace_back(std::move(top.GetTask()));
|
|
delayed_tasks_.pop();
|
|
if (type == FlushType::kSingle) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (delayed_tasks_.empty()) {
|
|
return fml::TimePoint::Max();
|
|
} else {
|
|
return delayed_tasks_.top().GetTargetTime();
|
|
}
|
|
}
|
|
|
|
size_t MessageLoopTaskQueue::GetNumPendingTasks() {
|
|
std::lock_guard<std::mutex> lock(delayed_tasks_mutex_);
|
|
return delayed_tasks_.size();
|
|
}
|
|
|
|
void MessageLoopTaskQueue::AddTaskObserver(intptr_t key,
|
|
fml::closure callback) {
|
|
std::lock_guard<std::mutex> observers_lock(observers_mutex_);
|
|
task_observers_[key] = std::move(callback);
|
|
}
|
|
|
|
void MessageLoopTaskQueue::RemoveTaskObserver(intptr_t key) {
|
|
std::lock_guard<std::mutex> observers_lock(observers_mutex_);
|
|
task_observers_.erase(key);
|
|
}
|
|
|
|
void MessageLoopTaskQueue::NotifyObservers() {
|
|
std::lock_guard<std::mutex> observers_lock(observers_mutex_);
|
|
for (const auto& observer : task_observers_) {
|
|
observer.second();
|
|
}
|
|
}
|
|
|
|
// Thread safety analysis disabled as it does not account for defered locks.
|
|
void MessageLoopTaskQueue::Swap(MessageLoopTaskQueue& other)
|
|
FML_NO_THREAD_SAFETY_ANALYSIS {
|
|
// task_observers locks
|
|
std::unique_lock<std::mutex> o1(observers_mutex_, std::defer_lock);
|
|
std::unique_lock<std::mutex> o2(other.observers_mutex_, std::defer_lock);
|
|
|
|
// delayed_tasks locks
|
|
std::unique_lock<std::mutex> d1(delayed_tasks_mutex_, std::defer_lock);
|
|
std::unique_lock<std::mutex> d2(other.delayed_tasks_mutex_, std::defer_lock);
|
|
|
|
std::lock(o1, o2, d1, d2);
|
|
|
|
std::swap(task_observers_, other.task_observers_);
|
|
std::swap(delayed_tasks_, other.delayed_tasks_);
|
|
}
|
|
|
|
} // namespace fml
|