@@ -27,7 +27,20 @@ bool ReactorGLES::IsValid() const {
27
27
return is_valid_;
28
28
}
29
29
30
+ ReactorGLES::WorkerID ReactorGLES::AddWorker (std::weak_ptr<Worker> worker) {
31
+ Lock lock (workers_mutex_);
32
+ auto id = WorkerID{};
33
+ workers_[id] = std::move (worker);
34
+ return id;
35
+ }
36
+
37
+ bool ReactorGLES::RemoveWorker (WorkerID worker) {
38
+ Lock lock (workers_mutex_);
39
+ return workers_.erase (worker) == 1 ;
40
+ }
41
+
30
42
bool ReactorGLES::HasPendingOperations () const {
43
+ Lock ops_lock (ops_mutex_);
31
44
return !pending_operations_.empty () || !gl_handles_to_collect_.empty ();
32
45
}
33
46
@@ -37,6 +50,7 @@ const ProcTableGLES& ReactorGLES::GetProcTable() const {
37
50
}
38
51
39
52
std::optional<GLuint> ReactorGLES::GetGLHandle (const HandleGLES& handle) const {
53
+ ReaderLock handles_lock (handles_mutex_);
40
54
auto found = live_gl_handles_.find (handle);
41
55
if (found != live_gl_handles_.end ()) {
42
56
return found->second ;
@@ -48,8 +62,13 @@ bool ReactorGLES::AddOperation(Operation operation) {
48
62
if (!operation) {
49
63
return false ;
50
64
}
51
- pending_operations_.emplace_back (std::move (operation));
52
- return React ();
65
+ {
66
+ Lock ops_lock (ops_mutex_);
67
+ pending_operations_.emplace_back (std::move (operation));
68
+ }
69
+ // Attempt a reaction if able but it is not an error if this isn't possible.
70
+ [[maybe_unused]] auto result = React ();
71
+ return true ;
53
72
}
54
73
55
74
static std::optional<GLuint> CreateGLHandle (const ProcTableGLES& gl,
@@ -109,24 +128,30 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type) {
109
128
if (new_handle.IsDead ()) {
110
129
return HandleGLES::DeadHandle ();
111
130
}
131
+ WriterLock handles_lock (handles_mutex_);
112
132
live_gl_handles_[new_handle] =
113
133
in_reaction_ ? CreateGLHandle (GetProcTable (), type) : std::nullopt;
114
134
return new_handle;
115
135
}
116
136
117
137
void ReactorGLES::CollectHandle (HandleGLES handle) {
138
+ WriterLock handles_lock (handles_mutex_);
118
139
auto live_handle = live_gl_handles_.find (handle);
119
140
if (live_handle == live_gl_handles_.end ()) {
120
141
return ;
121
142
}
122
143
if (live_handle->second .has_value ()) {
144
+ Lock ops_lock (ops_mutex_);
123
145
gl_handles_to_collect_[live_handle->first ] = live_handle->second .value ();
124
146
}
125
147
live_gl_handles_.erase (live_handle);
126
148
}
127
149
128
150
bool ReactorGLES::React () {
129
151
TRACE_EVENT0 (" impeller" , " ReactorGLES::React" );
152
+ if (!CanReactOnCurrentThread ()) {
153
+ return false ;
154
+ }
130
155
in_reaction_ = true ;
131
156
fml::ScopedCleanupClosure reset_in_reaction ([&]() { in_reaction_ = false ; });
132
157
while (HasPendingOperations ()) {
@@ -165,7 +190,13 @@ bool ReactorGLES::ReactOnce() {
165
190
// ----------------------------------------------------------------------------
166
191
// / Collect all the handles for whom there is a GL handle sibling.
167
192
// /
168
- for (const auto & handle_to_collect : gl_handles_to_collect_) {
193
+ decltype (gl_handles_to_collect_) gl_handles_to_collect;
194
+ {
195
+ Lock ops_lock (ops_mutex_);
196
+ std::swap (gl_handles_to_collect_, gl_handles_to_collect);
197
+ FML_DCHECK (gl_handles_to_collect_.empty ());
198
+ }
199
+ for (const auto & handle_to_collect : gl_handles_to_collect) {
169
200
if (!CollectGLHandle (gl, // proc table
170
201
handle_to_collect.first .type , // handle type
171
202
handle_to_collect.second // GL handle name
@@ -174,26 +205,52 @@ bool ReactorGLES::ReactOnce() {
174
205
return false ;
175
206
}
176
207
}
177
- gl_handles_to_collect_.clear ();
178
208
179
209
// ----------------------------------------------------------------------------
180
210
// / Make sure all pending handles have a GL handle sibling.
181
211
// /
182
- for (auto & live_handle : live_gl_handles_) {
183
- if (live_handle.second .has_value ()) {
184
- // Already a realized GL handle.
185
- continue ;
186
- }
187
- auto gl_handle = CreateGLHandle (gl, live_handle.first .type );
188
- if (!gl_handle.has_value ()) {
189
- VALIDATION_LOG << " Could not create GL handle." ;
190
- return false ;
212
+ {
213
+ WriterLock handles_lock (handles_mutex_);
214
+ for (auto & live_handle : live_gl_handles_) {
215
+ if (live_handle.second .has_value ()) {
216
+ // Already a realized GL handle.
217
+ continue ;
218
+ }
219
+ auto gl_handle = CreateGLHandle (gl, live_handle.first .type );
220
+ if (!gl_handle.has_value ()) {
221
+ VALIDATION_LOG << " Could not create GL handle." ;
222
+ return false ;
223
+ }
224
+ live_handle.second = gl_handle;
191
225
}
192
- live_handle.second = gl_handle;
193
226
}
194
227
195
- if (can_set_debug_labels_) {
196
- for (const auto & label : pending_debug_labels_) {
228
+ // ----------------------------------------------------------------------------
229
+ // / Flush all pending operations in order.
230
+ // /
231
+ decltype (pending_operations_) pending_operations;
232
+ {
233
+ Lock ops_lock (ops_mutex_);
234
+ std::swap (pending_operations_, pending_operations);
235
+ FML_DCHECK (pending_operations_.empty ());
236
+ }
237
+ for (const auto & operation : pending_operations) {
238
+ TRACE_EVENT0 (" impeller" , " ReactorGLES::Operation" );
239
+ operation (*this );
240
+ }
241
+
242
+ // ----------------------------------------------------------------------------
243
+ // / Make sure all pending debug labels have been flushed.
244
+ // /
245
+ decltype (pending_debug_labels_) pending_debug_labels;
246
+ {
247
+ WriterLock handles_lock (handles_mutex_);
248
+ std::swap (pending_debug_labels_, pending_debug_labels);
249
+ FML_DCHECK (pending_debug_labels_.empty ());
250
+ }
251
+ if (!pending_debug_labels.empty ()) {
252
+ ReaderLock handles_lock (handles_mutex_);
253
+ for (const auto & label : pending_debug_labels) {
197
254
auto live_handle = live_gl_handles_.find (label.first );
198
255
if (live_handle == live_gl_handles_.end () ||
199
256
!live_handle->second .has_value ()) {
@@ -205,16 +262,6 @@ bool ReactorGLES::ReactOnce() {
205
262
);
206
263
}
207
264
}
208
- pending_debug_labels_.clear ();
209
-
210
- // ----------------------------------------------------------------------------
211
- // / Flush all pending operations in order.
212
- // /
213
- auto operations = std::move (pending_operations_);
214
- for (const auto & operation : operations) {
215
- operation (*this );
216
- }
217
- pending_operations_.clear ();
218
265
219
266
return true ;
220
267
}
@@ -229,18 +276,27 @@ void ReactorGLES::SetDebugLabel(const HandleGLES& handle, std::string label) {
229
276
if (handle.IsDead ()) {
230
277
return ;
231
278
}
232
- if (in_reaction_) {
233
- if (auto found = live_gl_handles_.find (handle);
234
- found != live_gl_handles_.end () && found->second .has_value ()) {
235
- GetProcTable ().SetDebugLabel (
236
- ToDebugResourceType (found->first .type ), // type
237
- found->second .value (), // name
238
- label // label
239
- );
240
- return ;
279
+ WriterLock handles_lock (handles_mutex_);
280
+ pending_debug_labels_[handle] = std::move (label);
281
+ }
282
+
283
+ bool ReactorGLES::CanReactOnCurrentThread () const {
284
+ std::vector<WorkerID> dead_workers;
285
+ Lock lock (workers_mutex_);
286
+ for (const auto & worker : workers_) {
287
+ auto worker_ptr = worker.second .lock ();
288
+ if (!worker_ptr) {
289
+ dead_workers.push_back (worker.first );
290
+ continue ;
291
+ }
292
+ if (worker_ptr->CanReactorReactOnCurrentThreadNow (*this )) {
293
+ return true ;
241
294
}
242
295
}
243
- pending_debug_labels_[handle] = std::move (label);
296
+ for (const auto & worker_id : dead_workers) {
297
+ workers_.erase (worker_id);
298
+ }
299
+ return false ;
244
300
}
245
301
246
302
} // namespace impeller
0 commit comments