#define FML_USED_ON_EMBEDDER
#include "base/include/fml/task_source.h"
namespace lynx {
namespace fml {
namespace {
constexpr int64_t kIdlePeriod = 50;
}
TaskSource::TaskSource(TaskQueueId task_queue_id)
: task_queue_id_(task_queue_id) {
primary_task_queue_.reserve(64);
emergency_task_queue_.reserve(32);
micro_task_queue_.reserve(32);
}
TaskSource::~TaskSource() { ShutDown(); }
void TaskSource::ShutDown() { TakePendingTasks(); }
TaskSource::PendingTasks TaskSource::TakePendingTasks() {
PendingTasks pending_tasks;
pending_tasks.primary = std::move(primary_task_queue_);
pending_tasks.emergency = std::move(emergency_task_queue_);
pending_tasks.idle = std::move(idle_task_queue_);
pending_tasks.micro = std::move(micro_task_queue_);
primary_task_queue_ = {};
emergency_task_queue_ = {};
idle_task_queue_ = {};
micro_task_queue_ = {};
return pending_tasks;
}
void TaskSource::RegisterTask(DelayedTask task) {
switch (task.GetTaskSourceGrade()) {
case TaskSourceGrade::kUserInteraction:
primary_task_queue_.push(std::move(task));
break;
case TaskSourceGrade::kUnspecified:
primary_task_queue_.push(std::move(task));
break;
case TaskSourceGrade::kEmergency:
emergency_task_queue_.push(std::move(task));
break;
case TaskSourceGrade::kIdle:
idle_task_queue_.push(std::move(task));
break;
case TaskSourceGrade::kMicrotask:
micro_task_queue_.push(std::move(task));
break;
}
}
void TaskSource::PopTask(TaskSourceGrade grade) {
switch (grade) {
case TaskSourceGrade::kUserInteraction:
primary_task_queue_.pop();
break;
case TaskSourceGrade::kUnspecified:
primary_task_queue_.pop();
break;
case TaskSourceGrade::kEmergency:
emergency_task_queue_.pop();
break;
case TaskSourceGrade::kIdle:
idle_task_queue_.pop();
break;
case TaskSourceGrade::kMicrotask:
micro_task_queue_.pop();
break;
}
}
size_t TaskSource::GetNumPendingTasks() const {
return primary_task_queue_.size() + emergency_task_queue_.size() +
idle_task_queue_.size() + micro_task_queue_.size();
}
bool TaskSource::IsEmpty() const { return GetNumPendingTasks() == 0; }
TaskSource::TopTask TaskSource::Top() const {
if (!micro_task_queue_.empty()) {
const auto& microtask_top = micro_task_queue_.top();
return {
.task_queue_id = task_queue_id_,
.task = microtask_top,
};
}
if (!emergency_task_queue_.empty()) {
const auto& emergency_top = emergency_task_queue_.top();
return {
.task_queue_id = task_queue_id_,
.task = emergency_top,
};
}
if (!primary_task_queue_.empty()) {
const auto& primary_top = primary_task_queue_.top();
if (idle_task_queue_.empty() ||
(primary_top.GetTargetTime() - TimePoint::Now()).ToMilliseconds() <=
kIdlePeriod) {
return {
.task_queue_id = task_queue_id_,
.task = primary_top,
};
}
}
LYNX_BASE_CHECK(!idle_task_queue_.empty());
const auto& idle_top = idle_task_queue_.front();
return {
.task_queue_id = task_queue_id_,
.task = idle_top,
};
}
const DelayedTask* TaskSource::TopOrNull() const {
if (!micro_task_queue_.empty()) {
return µ_task_queue_.top();
}
if (!emergency_task_queue_.empty()) {
return &emergency_task_queue_.top();
}
if (!primary_task_queue_.empty()) {
const auto& primary_top = primary_task_queue_.top();
if (idle_task_queue_.empty() ||
(primary_top.GetTargetTime() - TimePoint::Now()).ToMilliseconds() <=
kIdlePeriod) {
return &primary_top;
}
}
if (!idle_task_queue_.empty()) {
return &idle_task_queue_.front();
}
return nullptr;
}
}
}