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 
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 
19  std::shared_ptr<fml::ConcurrentTaskRunner> worker_task_runner)
20  : worker_task_runner_(std::move(worker_task_runner)) {}
21 
23  FinishAllJobs();
24 }
25 
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 
113  if (auto job = TakeJob(desc)) {
114  job();
115  }
116 }
117 
118 } // namespace impeller
bool PostJobForDescriptor(const PipelineDescriptor &desc, const fml::closure &job)
Post a compile job for the specified descriptor.
static std::shared_ptr< PipelineCompileQueue > Create(std::shared_ptr< fml::ConcurrentTaskRunner > worker_task_runner)
PipelineCompileQueue(const PipelineCompileQueue &)=delete
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: comparable.h:95