forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
message_loop_task_queues.h
167 lines (119 loc) · 5.14 KB
/
message_loop_task_queues.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_
#define FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_
#include <map>
#include <memory>
#include <mutex>
#include <set>
#include <vector>
#include "flutter/fml/closure.h"
#include "flutter/fml/delayed_task.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/ref_counted.h"
#include "flutter/fml/synchronization/shared_mutex.h"
#include "flutter/fml/task_queue_id.h"
#include "flutter/fml/task_source.h"
#include "flutter/fml/wakeable.h"
namespace fml {
static const TaskQueueId _kUnmerged = TaskQueueId(TaskQueueId::kUnmerged);
/// A collection of tasks and observers associated with one TaskQueue.
///
/// Often a TaskQueue has a one-to-one relationship with a fml::MessageLoop,
/// this isn't the case when TaskQueues are merged via
/// \p fml::MessageLoopTaskQueues::Merge.
class TaskQueueEntry {
public:
using TaskObservers = std::map<intptr_t, fml::closure>;
Wakeable* wakeable;
TaskObservers task_observers;
std::unique_ptr<TaskSource> task_source;
/// Set of the TaskQueueIds which is owned by this TaskQueue. If the set is
/// empty, this TaskQueue does not own any other TaskQueues.
std::set<TaskQueueId> owner_of;
/// Identifies the TaskQueue that subsumes this TaskQueue. If it is _kUnmerged
/// it indicates that this TaskQueue is not owned by any other TaskQueue.
TaskQueueId subsumed_by;
TaskQueueId created_for;
explicit TaskQueueEntry(TaskQueueId created_for);
private:
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(TaskQueueEntry);
};
enum class FlushType {
kSingle,
kAll,
};
/// A singleton container for all tasks and observers associated with all
/// fml::MessageLoops.
///
/// This also wakes up the loop at the required times.
/// \see fml::MessageLoop
/// \see fml::Wakeable
class MessageLoopTaskQueues {
public:
// Lifecycle.
static MessageLoopTaskQueues* GetInstance();
TaskQueueId CreateTaskQueue();
void Dispose(TaskQueueId queue_id);
void DisposeTasks(TaskQueueId queue_id);
// Tasks methods.
void RegisterTask(TaskQueueId queue_id,
const fml::closure& task,
fml::TimePoint target_time,
fml::TaskSourceGrade task_source_grade =
fml::TaskSourceGrade::kUnspecified);
bool HasPendingTasks(TaskQueueId queue_id) const;
fml::closure GetNextTaskToRun(TaskQueueId queue_id, fml::TimePoint from_time);
size_t GetNumPendingTasks(TaskQueueId queue_id) const;
static TaskSourceGrade GetCurrentTaskSourceGrade();
// Observers methods.
void AddTaskObserver(TaskQueueId queue_id,
intptr_t key,
const fml::closure& callback);
void RemoveTaskObserver(TaskQueueId queue_id, intptr_t key);
std::vector<fml::closure> GetObserversToNotify(TaskQueueId queue_id) const;
// Misc.
void SetWakeable(TaskQueueId queue_id, fml::Wakeable* wakeable);
// Invariants for merge and un-merge
// 1. RegisterTask will always submit to the queue_id that is passed
// to it. It is not aware of whether a queue is merged or not. Same with
// task observers.
// 2. When we get the tasks to run now, we look at both the queue_ids
// for the owner and the subsumed task queues.
// 3. One TaskQueue can subsume multiple other TaskQueues. A TaskQueue can be
// in exactly one of the following three states:
// a. Be an owner of multiple other TaskQueues.
// b. Be subsumed by a TaskQueue (an owner can never be subsumed).
// c. Be independent, i.e, neither owner nor be subsumed.
//
// Methods currently aware of the merged state of the queues:
// HasPendingTasks, GetNextTaskToRun, GetNumPendingTasks
bool Merge(TaskQueueId owner, TaskQueueId subsumed);
// Will return false if the owner has not been merged before, or owner was
// subsumed by others, or subsumed wasn't subsumed by others, or owner
// didn't own the given subsumed queue id.
bool Unmerge(TaskQueueId owner, TaskQueueId subsumed);
/// Returns \p true if \p owner owns the \p subsumed task queue.
bool Owns(TaskQueueId owner, TaskQueueId subsumed) const;
// Returns the subsumed task queue if any or |TaskQueueId::kUnmerged|
// otherwise.
std::set<TaskQueueId> GetSubsumedTaskQueueId(TaskQueueId owner) const;
void PauseSecondarySource(TaskQueueId queue_id);
void ResumeSecondarySource(TaskQueueId queue_id);
private:
class MergedQueuesRunner;
MessageLoopTaskQueues();
~MessageLoopTaskQueues();
void WakeUpUnlocked(TaskQueueId queue_id, fml::TimePoint time) const;
bool HasPendingTasksUnlocked(TaskQueueId queue_id) const;
TaskSource::TopTask PeekNextTaskUnlocked(TaskQueueId owner) const;
fml::TimePoint GetNextWakeTimeUnlocked(TaskQueueId queue_id) const;
mutable std::mutex queue_mutex_;
std::map<TaskQueueId, std::unique_ptr<TaskQueueEntry>> queue_entries_;
size_t task_queue_id_counter_;
std::atomic_int order_;
FML_DISALLOW_COPY_ASSIGN_AND_MOVE(MessageLoopTaskQueues);
};
} // namespace fml
#endif // FLUTTER_FML_MESSAGE_LOOP_TASK_QUEUES_H_