| Flutter Impeller |

pipeline_compile_queue.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/pipeline_compile_queue.h"
6
7 #include "flutter/fml/logging.h"
8 #include "flutter/fml/trace_event.h"
9
10 namespace impeller {
11
12 std::shared_ptr<PipelineCompileQueue> PipelineCompileQueue::Create(
13 std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner) {
14 return std::shared_ptr<PipelineCompileQueue>(
15 new PipelineCompileQueue(std::move(worker_task_runner)));
16 }
17
18 PipelineCompileQueue::PipelineCompileQueue(
19 std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner)
20 : worker_task_runner_(std::move(worker_task_runner)) {}
21
22 PipelineCompileQueue::~PipelineCompileQueue() {
23 FinishAllJobs();
24 }
25
26 bool PipelineCompileQueue::PostJobForDescriptor(const PipelineDescriptor& desc,
27 const fml::closure& job) {
28 if (!job) {
29 return false;
30 }
31
32 {
33 Lock lock(pending_jobs_mutex_);
34 auto insertion_result = pending_jobs_.insert(std::make_pair(desc, job));
35 if (!insertion_result.second) {
36 // This bit is being extremely conservative. If insertion did not take
37 // place, someone gave the compile queue a job for the same description.
38 // This is highly unusual but technically not impossible. Just run the job
39 // eagerly.
40 FML_LOG(ERROR) << "Got multiple compile jobs for the same descriptor. "
41 "Running eagerly.";
42 // Don't invoke the job here has there are we have currently acquired a
43 // mutex.
44 worker_task_runner_->PostTask(job);
45 return true;
46 }
47 }
48
49 worker_task_runner_->PostTask([weak_queue = weak_from_this()]() {
50 if (auto queue = weak_queue.lock()) {
51 queue->DoOneJob();
52 }
53 });
54 return true;
55 }
56
57 fml::closure PipelineCompileQueue::TakeNextJob() {
58 Lock lock(pending_jobs_mutex_);
59 if (pending_jobs_.empty()) {
60 return nullptr;
61 }
62 auto job_iterator = pending_jobs_.begin();
63 auto job = job_iterator->second;
64 pending_jobs_.erase(job_iterator);
65 return job;
66 }
67
68 fml::closure PipelineCompileQueue::TakeJob(const PipelineDescriptor& desc) {
69 Lock lock(pending_jobs_mutex_);
70 auto found = pending_jobs_.find(desc);
71 if (found == pending_jobs_.end()) {
72 return nullptr;
73 }
74 // The pipeline compile job was somewhere in the task queue. However, a
75 // rendering operation needed the job to be done ASAP. Instead of waiting for
76 // the pipeline compile queue to eventually get to finishing job, the thread
77 // waiting on the job just decided to take the job from the queue and do it
78 // itself. If there were jobs ahead of this one, it means that they were
79 // mis-prioritized. This counter dumps the number of job re-prioritizations.
80 priorities_elevated_++;
81 FML_TRACE_COUNTER("impeller", "PipelineCompileQueue",
82 reinterpret_cast<int64_t>(this), // Trace Counter ID
83 "PrioritiesElevated", priorities_elevated_);
84 auto job = found->second;
85 pending_jobs_.erase(found);
86 return job;
87 }
88
89 void PipelineCompileQueue::DoOneJob() {
90 if (auto job = TakeNextJob()) {
91 job();
92 }
93 }
94
95 void PipelineCompileQueue::FinishAllJobs() {
96 // This doesn't have to be fast. Just ensures the task queue is flushed when
97 // the compile queue is shutting down with jobs still in it.
98 while (true) {
99 bool has_jobs = false;
100 {
101 Lock lock(pending_jobs_mutex_);
102 has_jobs = !pending_jobs_.empty();
103 }
104 if (!has_jobs) {
105 return;
106 }
107 // Allow any remaining worker threads to take jobs from this queue.
108 DoOneJob();
109 }
110 }
111
112 void PipelineCompileQueue::PerformJobEagerly(const PipelineDescriptor& desc) {
113 if (auto job = TakeJob(desc)) {
114 job();
115 }
116 }
117
118 } // namespace impeller
impeller::Lock
Definition: thread.h:72
impeller::PipelineCompileQueue::PostJobForDescriptor
bool PostJobForDescriptor(const PipelineDescriptor &desc, const fml::closure &job)
Post a compile job for the specified descriptor.
Definition: pipeline_compile_queue.cc:26
impeller::PipelineCompileQueue::Create
static std::shared_ptr< PipelineCompileQueue > Create(std::shared_ptr< fml::ConcurrentTaskRunner > worker_task_runner)
Definition: pipeline_compile_queue.cc:12
impeller::PipelineCompileQueue::PipelineCompileQueue
PipelineCompileQueue(const PipelineCompileQueue &)=delete
impeller::PipelineCompileQueue::~PipelineCompileQueue
virtual ~PipelineCompileQueue()
Definition: pipeline_compile_queue.cc:22
impeller::PipelineCompileQueue::PerformJobEagerly
void PerformJobEagerly(const PipelineDescriptor &desc)
If the task has not yet been done, perform it eagerly on the calling thread. This can be used in lieu...
Definition: pipeline_compile_queue.cc:112
impeller::PipelineDescriptor
Definition: pipeline_descriptor.h:24
impeller
Definition: allocation.cc:12
std
Definition: comparable.h:95
pipeline_compile_queue.h