Flutter Engine
fml::MessageLoopTaskQueues Class Reference

#include <message_loop_task_queues.h>

Inheritance diagram for fml::MessageLoopTaskQueues:
fml::RefCountedThreadSafe< MessageLoopTaskQueues > fml::internal::RefCountedThreadSafeBase

Public Member Functions

TaskQueueId CreateTaskQueue ()
 
void Dispose (TaskQueueId queue_id)
 
void DisposeTasks (TaskQueueId queue_id)
 
void RegisterTask (TaskQueueId queue_id, const fml::closure &task, fml::TimePoint target_time)
 
bool HasPendingTasks (TaskQueueId queue_id) const
 
fml::closure GetNextTaskToRun (TaskQueueId queue_id, fml::TimePoint from_time)
 
size_t GetNumPendingTasks (TaskQueueId queue_id) const
 
void AddTaskObserver (TaskQueueId queue_id, intptr_t key, const fml::closure &callback)
 
void RemoveTaskObserver (TaskQueueId queue_id, intptr_t key)
 
std::vector< fml::closureGetObserversToNotify (TaskQueueId queue_id) const
 
void SetWakeable (TaskQueueId queue_id, fml::Wakeable *wakeable)
 
bool Merge (TaskQueueId owner, TaskQueueId subsumed)
 
bool Unmerge (TaskQueueId owner)
 
bool Owns (TaskQueueId owner, TaskQueueId subsumed) const
 
- Public Member Functions inherited from fml::RefCountedThreadSafe< MessageLoopTaskQueues >
void Release () const
 
- Public Member Functions inherited from fml::internal::RefCountedThreadSafeBase
void AddRef () const
 
bool HasOneRef () const
 
void AssertHasOneRef () const
 

Static Public Member Functions

static fml::RefPtr< MessageLoopTaskQueuesGetInstance ()
 

Additional Inherited Members

- Protected Member Functions inherited from fml::RefCountedThreadSafe< MessageLoopTaskQueues >
 RefCountedThreadSafe ()
 
 ~RefCountedThreadSafe ()
 
- Protected Member Functions inherited from fml::internal::RefCountedThreadSafeBase
 RefCountedThreadSafeBase ()
 
 ~RefCountedThreadSafeBase ()
 
bool Release () const
 
void Adopt ()
 

Detailed Description

Definition at line 65 of file message_loop_task_queues.h.

Member Function Documentation

◆ AddTaskObserver()

void fml::MessageLoopTaskQueues::AddTaskObserver ( TaskQueueId  queue_id,
intptr_t  key,
const fml::closure callback 
)

Definition at line 139 of file message_loop_task_queues.cc.

References FML_DCHECK.

141  {
142  std::lock_guard guard(queue_mutex_);
143  FML_DCHECK(callback != nullptr) << "Observer callback must be non-null.";
144  queue_entries_.at(queue_id)->task_observers[key] = callback;
145 }
#define FML_DCHECK(condition)
Definition: logging.h:86

◆ CreateTaskQueue()

TaskQueueId fml::MessageLoopTaskQueues::CreateTaskQueue ( )

Definition at line 37 of file message_loop_task_queues.cc.

37  {
38  std::lock_guard guard(queue_mutex_);
39  TaskQueueId loop_id = TaskQueueId(task_queue_id_counter_);
40  ++task_queue_id_counter_;
41  queue_entries_[loop_id] = std::make_unique<TaskQueueEntry>();
42  return loop_id;
43 }

◆ Dispose()

void fml::MessageLoopTaskQueues::Dispose ( TaskQueueId  queue_id)

Definition at line 50 of file message_loop_task_queues.cc.

References fml::_kUnmerged, and FML_DCHECK.

50  {
51  std::lock_guard guard(queue_mutex_);
52  const auto& queue_entry = queue_entries_.at(queue_id);
53  FML_DCHECK(queue_entry->subsumed_by == _kUnmerged);
54  TaskQueueId subsumed = queue_entry->owner_of;
55  queue_entries_.erase(queue_id);
56  if (subsumed != _kUnmerged) {
57  queue_entries_.erase(subsumed);
58  }
59 }
#define FML_DCHECK(condition)
Definition: logging.h:86
static const TaskQueueId _kUnmerged

◆ DisposeTasks()

void fml::MessageLoopTaskQueues::DisposeTasks ( TaskQueueId  queue_id)

Definition at line 61 of file message_loop_task_queues.cc.

References fml::_kUnmerged, and FML_DCHECK.

61  {
62  std::lock_guard guard(queue_mutex_);
63  const auto& queue_entry = queue_entries_.at(queue_id);
64  FML_DCHECK(queue_entry->subsumed_by == _kUnmerged);
65  TaskQueueId subsumed = queue_entry->owner_of;
66  queue_entry->delayed_tasks = {};
67  if (subsumed != _kUnmerged) {
68  queue_entries_.at(subsumed)->delayed_tasks = {};
69  }
70 }
#define FML_DCHECK(condition)
Definition: logging.h:86
static const TaskQueueId _kUnmerged

◆ GetInstance()

fml::RefPtr< MessageLoopTaskQueues > fml::MessageLoopTaskQueues::GetInstance ( )
static

Definition at line 29 of file message_loop_task_queues.cc.

Referenced by fml::benchmarking::BM_RegisterAndGetTasks(), fml::TaskRunnerChecker::RunsOnTheSameThread(), fml::testing::TEST(), and fml::testing::TestNotifyObservers().

29  {
30  std::scoped_lock creation(creation_mutex_);
31  if (!instance_) {
32  instance_ = fml::MakeRefCounted<MessageLoopTaskQueues>();
33  }
34  return instance_;
35 }

◆ GetNextTaskToRun()

fml::closure fml::MessageLoopTaskQueues::GetNextTaskToRun ( TaskQueueId  queue_id,
fml::TimePoint  from_time 
)

Definition at line 91 of file message_loop_task_queues.cc.

References fml::_kUnmerged, and fml::TimePoint::Max().

92  {
93  std::lock_guard guard(queue_mutex_);
94  if (!HasPendingTasksUnlocked(queue_id)) {
95  return nullptr;
96  }
97  TaskQueueId top_queue = _kUnmerged;
98  const auto& top = PeekNextTaskUnlocked(queue_id, top_queue);
99 
100  if (!HasPendingTasksUnlocked(queue_id)) {
101  WakeUpUnlocked(queue_id, fml::TimePoint::Max());
102  } else {
103  WakeUpUnlocked(queue_id, GetNextWakeTimeUnlocked(queue_id));
104  }
105 
106  if (top.GetTargetTime() > from_time) {
107  return nullptr;
108  }
109  fml::closure invocation = top.GetTask();
110  queue_entries_.at(top_queue)->delayed_tasks.pop();
111  return invocation;
112 }
std::function< void()> closure
Definition: closure.h:14
static constexpr TimePoint Max()
Definition: time_point.h:32
static const TaskQueueId _kUnmerged

◆ GetNumPendingTasks()

size_t fml::MessageLoopTaskQueues::GetNumPendingTasks ( TaskQueueId  queue_id) const

Definition at line 121 of file message_loop_task_queues.cc.

References fml::_kUnmerged.

121  {
122  std::lock_guard guard(queue_mutex_);
123  const auto& queue_entry = queue_entries_.at(queue_id);
124  if (queue_entry->subsumed_by != _kUnmerged) {
125  return 0;
126  }
127 
128  size_t total_tasks = 0;
129  total_tasks += queue_entry->delayed_tasks.size();
130 
131  TaskQueueId subsumed = queue_entry->owner_of;
132  if (subsumed != _kUnmerged) {
133  const auto& subsumed_entry = queue_entries_.at(subsumed);
134  total_tasks += subsumed_entry->delayed_tasks.size();
135  }
136  return total_tasks;
137 }
static const TaskQueueId _kUnmerged

◆ GetObserversToNotify()

std::vector< fml::closure > fml::MessageLoopTaskQueues::GetObserversToNotify ( TaskQueueId  queue_id) const

Definition at line 153 of file message_loop_task_queues.cc.

References fml::_kUnmerged.

154  {
155  std::lock_guard guard(queue_mutex_);
156  std::vector<fml::closure> observers;
157 
158  if (queue_entries_.at(queue_id)->subsumed_by != _kUnmerged) {
159  return observers;
160  }
161 
162  for (const auto& observer : queue_entries_.at(queue_id)->task_observers) {
163  observers.push_back(observer.second);
164  }
165 
166  TaskQueueId subsumed = queue_entries_.at(queue_id)->owner_of;
167  if (subsumed != _kUnmerged) {
168  for (const auto& observer : queue_entries_.at(subsumed)->task_observers) {
169  observers.push_back(observer.second);
170  }
171  }
172 
173  return observers;
174 }
static const TaskQueueId _kUnmerged

◆ HasPendingTasks()

bool fml::MessageLoopTaskQueues::HasPendingTasks ( TaskQueueId  queue_id) const

Definition at line 86 of file message_loop_task_queues.cc.

86  {
87  std::lock_guard guard(queue_mutex_);
88  return HasPendingTasksUnlocked(queue_id);
89 }

◆ Merge()

bool fml::MessageLoopTaskQueues::Merge ( TaskQueueId  owner,
TaskQueueId  subsumed 
)

Definition at line 184 of file message_loop_task_queues.cc.

References fml::_kUnmerged.

Referenced by fml::RasterThreadMerger::MergeWithLease().

184  {
185  if (owner == subsumed) {
186  return true;
187  }
188  std::lock_guard guard(queue_mutex_);
189  auto& owner_entry = queue_entries_.at(owner);
190  auto& subsumed_entry = queue_entries_.at(subsumed);
191 
192  if (owner_entry->owner_of == subsumed) {
193  return true;
194  }
195 
196  std::vector<TaskQueueId> owner_subsumed_keys = {
197  owner_entry->owner_of, owner_entry->subsumed_by, subsumed_entry->owner_of,
198  subsumed_entry->subsumed_by};
199 
200  for (auto key : owner_subsumed_keys) {
201  if (key != _kUnmerged) {
202  return false;
203  }
204  }
205 
206  owner_entry->owner_of = subsumed;
207  subsumed_entry->subsumed_by = owner;
208 
209  if (HasPendingTasksUnlocked(owner)) {
210  WakeUpUnlocked(owner, GetNextWakeTimeUnlocked(owner));
211  }
212 
213  return true;
214 }
static const TaskQueueId _kUnmerged

◆ Owns()

bool fml::MessageLoopTaskQueues::Owns ( TaskQueueId  owner,
TaskQueueId  subsumed 
) const

Definition at line 238 of file message_loop_task_queues.cc.

References fml::_kUnmerged, and FML_DCHECK.

Referenced by fml::RasterThreadMerger::RasterThreadMerger().

239  {
240  std::lock_guard guard(queue_mutex_);
241  return subsumed == queue_entries_.at(owner)->owner_of;
242 }

◆ RegisterTask()

void fml::MessageLoopTaskQueues::RegisterTask ( TaskQueueId  queue_id,
const fml::closure task,
fml::TimePoint  target_time 
)

Definition at line 72 of file message_loop_task_queues.cc.

References fml::_kUnmerged.

74  {
75  std::lock_guard guard(queue_mutex_);
76  size_t order = order_++;
77  const auto& queue_entry = queue_entries_.at(queue_id);
78  queue_entry->delayed_tasks.push({order, task, target_time});
79  TaskQueueId loop_to_wake = queue_id;
80  if (queue_entry->subsumed_by != _kUnmerged) {
81  loop_to_wake = queue_entry->subsumed_by;
82  }
83  WakeUpUnlocked(loop_to_wake, GetNextWakeTimeUnlocked(loop_to_wake));
84 }
static const TaskQueueId _kUnmerged

◆ RemoveTaskObserver()

void fml::MessageLoopTaskQueues::RemoveTaskObserver ( TaskQueueId  queue_id,
intptr_t  key 
)

Definition at line 147 of file message_loop_task_queues.cc.

148  {
149  std::lock_guard guard(queue_mutex_);
150  queue_entries_.at(queue_id)->task_observers.erase(key);
151 }

◆ SetWakeable()

void fml::MessageLoopTaskQueues::SetWakeable ( TaskQueueId  queue_id,
fml::Wakeable wakeable 
)

Definition at line 176 of file message_loop_task_queues.cc.

References FML_CHECK, and fml::TaskQueueEntry::wakeable.

177  {
178  std::lock_guard guard(queue_mutex_);
179  FML_CHECK(!queue_entries_.at(queue_id)->wakeable)
180  << "Wakeable can only be set once.";
181  queue_entries_.at(queue_id)->wakeable = wakeable;
182 }
#define FML_CHECK(condition)
Definition: logging.h:68

◆ Unmerge()

bool fml::MessageLoopTaskQueues::Unmerge ( TaskQueueId  owner)

Definition at line 216 of file message_loop_task_queues.cc.

References fml::_kUnmerged.

Referenced by fml::RasterThreadMerger::UnMergeNow().

216  {
217  std::lock_guard guard(queue_mutex_);
218  const auto& owner_entry = queue_entries_.at(owner);
219  const TaskQueueId subsumed = owner_entry->owner_of;
220  if (subsumed == _kUnmerged) {
221  return false;
222  }
223 
224  queue_entries_.at(subsumed)->subsumed_by = _kUnmerged;
225  owner_entry->owner_of = _kUnmerged;
226 
227  if (HasPendingTasksUnlocked(owner)) {
228  WakeUpUnlocked(owner, GetNextWakeTimeUnlocked(owner));
229  }
230 
231  if (HasPendingTasksUnlocked(subsumed)) {
232  WakeUpUnlocked(subsumed, GetNextWakeTimeUnlocked(subsumed));
233  }
234 
235  return true;
236 }
static const TaskQueueId _kUnmerged

The documentation for this class was generated from the following files: