Flutter Engine
message_loop_task_queues.h
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 #ifndef FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_
6 #define FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_
7 
8 #include <map>
9 #include <mutex>
10 #include <vector>
11 
12 #include "flutter/fml/closure.h"
13 #include "flutter/fml/delayed_task.h"
14 #include "flutter/fml/macros.h"
15 #include "flutter/fml/memory/ref_counted.h"
16 #include "flutter/fml/synchronization/shared_mutex.h"
17 #include "flutter/fml/wakeable.h"
18 
19 namespace fml {
20 
21 class TaskQueueId {
22  public:
23  static const size_t kUnmerged;
24 
25  explicit TaskQueueId(size_t value) : value_(value) {}
26 
27  operator int() const { return value_; }
28 
29  private:
30  size_t value_ = kUnmerged;
31 };
32 
34 
35 // This is keyed by the |TaskQueueId| and contains all the queue
36 // components that make up a single TaskQueue.
38  public:
39  using TaskObservers = std::map<intptr_t, fml::closure>;
43 
44  // Note: Both of these can be _kUnmerged, which indicates that
45  // this queue has not been merged or subsumed. OR exactly one
46  // of these will be _kUnmerged, if owner_of is _kUnmerged, it means
47  // that the queue has been subsumed or else it owns another queue.
50 
52 
53  private:
55 };
56 
57 enum class FlushType {
58  kSingle,
59  kAll,
60 };
61 
62 // This class keeps track of all the tasks and observers that
63 // need to be run on it's MessageLoopImpl. This also wakes up the
64 // loop at the required times.
66  : public fml::RefCountedThreadSafe<MessageLoopTaskQueues> {
67  public:
68  // Lifecycle.
69 
70  static fml::RefPtr<MessageLoopTaskQueues> GetInstance();
71 
72  TaskQueueId CreateTaskQueue();
73 
74  void Dispose(TaskQueueId queue_id);
75 
76  void DisposeTasks(TaskQueueId queue_id);
77 
78  // Tasks methods.
79 
80  void RegisterTask(TaskQueueId queue_id,
81  const fml::closure& task,
82  fml::TimePoint target_time);
83 
84  bool HasPendingTasks(TaskQueueId queue_id) const;
85 
86  fml::closure GetNextTaskToRun(TaskQueueId queue_id, fml::TimePoint from_time);
87 
88  size_t GetNumPendingTasks(TaskQueueId queue_id) const;
89 
90  // Observers methods.
91 
92  void AddTaskObserver(TaskQueueId queue_id,
93  intptr_t key,
94  const fml::closure& callback);
95 
96  void RemoveTaskObserver(TaskQueueId queue_id, intptr_t key);
97 
98  std::vector<fml::closure> GetObserversToNotify(TaskQueueId queue_id) const;
99 
100  // Misc.
101 
102  void SetWakeable(TaskQueueId queue_id, fml::Wakeable* wakeable);
103 
104  // Invariants for merge and un-merge
105  // 1. RegisterTask will always submit to the queue_id that is passed
106  // to it. It is not aware of whether a queue is merged or not. Same with
107  // task observers.
108  // 2. When we get the tasks to run now, we look at both the queue_ids
109  // for the owner, subsumed will spin.
110  // 3. Each task queue can only be merged and subsumed once.
111  //
112  // Methods currently aware of the merged state of the queues:
113  // HasPendingTasks, GetNextTaskToRun, GetNumPendingTasks
114 
115  // This method returns false if either the owner or subsumed has already been
116  // merged with something else.
117  bool Merge(TaskQueueId owner, TaskQueueId subsumed);
118 
119  // Will return false if the owner has not been merged before.
120  bool Unmerge(TaskQueueId owner);
121 
122  // Returns true if owner owns the subsumed task queue.
123  bool Owns(TaskQueueId owner, TaskQueueId subsumed) const;
124 
125  private:
126  class MergedQueuesRunner;
127 
129 
131 
132  void WakeUpUnlocked(TaskQueueId queue_id, fml::TimePoint time) const;
133 
134  bool HasPendingTasksUnlocked(TaskQueueId queue_id) const;
135 
136  const DelayedTask& PeekNextTaskUnlocked(TaskQueueId owner,
137  TaskQueueId& top_queue_id) const;
138 
139  fml::TimePoint GetNextWakeTimeUnlocked(TaskQueueId queue_id) const;
140 
141  static std::mutex creation_mutex_;
142  static fml::RefPtr<MessageLoopTaskQueues> instance_;
143 
144  mutable std::mutex queue_mutex_;
145  std::map<TaskQueueId, std::unique_ptr<TaskQueueEntry>> queue_entries_;
146 
147  size_t task_queue_id_counter_;
148 
149  std::atomic_int order_;
150 
154 };
155 
156 } // namespace fml
157 
158 #endif // FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_
#define FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TypeName)
Definition: macros.h:31
TaskQueueId owner_of
std::map< intptr_t, fml::closure > TaskObservers
#define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T)
Definition: ref_counted.h:125
Definition: ascii_trie.cc:9
std::function< void()> closure
Definition: closure.h:14
#define FML_FRIEND_MAKE_REF_COUNTED(T)
Definition: ref_counted.h:131
uint8_t value
TaskObservers task_observers
static const TaskQueueId _kUnmerged
DelayedTaskQueue delayed_tasks
Wakeable * wakeable
static const size_t kUnmerged
std::priority_queue< DelayedTask, std::deque< DelayedTask >, std::greater< DelayedTask > > DelayedTaskQueue
Definition: delayed_task.h:39
TaskQueueId subsumed_by