10
10
#include < third_party/tonic/dart_binding_macros.h>
11
11
#include < third_party/tonic/logging/dart_invoke.h>
12
12
13
+ #include " dart/runtime/include/dart_api.h"
13
14
#include " flutter/flow/view_holder.h"
14
15
#include " flutter/fml/thread_local.h"
15
16
#include " flutter/lib/ui/ui_dart_state.h"
16
17
17
18
namespace {
18
19
19
- using SceneHostBindings = std::unordered_map<zx_koid_t , flutter::SceneHost*>;
20
+ struct SceneHostBindingKey {
21
+ std::string isolate_service_id;
22
+ zx_koid_t koid;
20
23
21
- FML_THREAD_LOCAL fml::ThreadLocalUniquePtr<SceneHostBindings>
22
- tls_scene_host_bindings;
24
+ SceneHostBindingKey (const zx_koid_t koid,
25
+ const std::string isolate_service_id) {
26
+ this ->koid = koid;
27
+ this ->isolate_service_id = isolate_service_id;
28
+ }
23
29
24
- void SceneHost_constructor (Dart_NativeArguments args) {
25
- // This UI thread / Isolate contains at least 1 SceneHost. Initialize the
26
- // per-Isolate bindings.
27
- if (tls_scene_host_bindings.get () == nullptr ) {
28
- tls_scene_host_bindings.reset (new SceneHostBindings ());
30
+ bool operator ==(const SceneHostBindingKey& other) const {
31
+ return isolate_service_id == other.isolate_service_id && koid == other.koid ;
32
+ }
33
+ };
34
+
35
+ struct SceneHostBindingKeyHasher {
36
+ std::size_t operator ()(const SceneHostBindingKey& key) const {
37
+ std::size_t koid_hash = std::hash<zx_koid_t >()(key.koid );
38
+ std::size_t isolate_hash = std::hash<std::string>()(key.isolate_service_id );
39
+ return koid_hash ^ isolate_hash;
29
40
}
41
+ };
42
+
43
+ using SceneHostBindings = std::unordered_map<SceneHostBindingKey,
44
+ flutter::SceneHost*,
45
+ SceneHostBindingKeyHasher>;
46
+
47
+ static SceneHostBindings scene_host_bindings;
30
48
49
+ void SceneHost_constructor (Dart_NativeArguments args) {
31
50
tonic::DartCallConstructor (&flutter::SceneHost::Create, args);
32
51
}
33
52
34
- flutter::SceneHost* GetSceneHost (scenic::ResourceId id) {
35
- auto * bindings = tls_scene_host_bindings.get ();
36
- FML_DCHECK (bindings);
37
-
38
- auto binding = bindings->find (id);
39
- if (binding != bindings->end ()) {
53
+ flutter::SceneHost* GetSceneHost (scenic::ResourceId id,
54
+ std::string isolate_service_id) {
55
+ auto binding =
56
+ scene_host_bindings.find (SceneHostBindingKey (id, isolate_service_id));
57
+ if (binding == scene_host_bindings.end ()) {
58
+ return nullptr ;
59
+ } else {
40
60
return binding->second ;
41
61
}
62
+ }
42
63
43
- return nullptr ;
64
+ flutter::SceneHost* GetSceneHostForCurrentIsolate (scenic::ResourceId id) {
65
+ auto isolate = Dart_CurrentIsolate ();
66
+ if (!isolate) {
67
+ return nullptr ;
68
+ } else {
69
+ std::string isolate_service_id = Dart_IsolateServiceId (isolate);
70
+ return GetSceneHost (id, isolate_service_id);
71
+ }
44
72
}
45
73
46
74
void InvokeDartClosure (const tonic::DartPersistentValue& closure) {
@@ -107,23 +135,23 @@ fml::RefPtr<SceneHost> SceneHost::Create(
107
135
}
108
136
109
137
void SceneHost::OnViewConnected (scenic::ResourceId id) {
110
- auto * scene_host = GetSceneHost (id);
138
+ auto * scene_host = GetSceneHostForCurrentIsolate (id);
111
139
112
140
if (scene_host && !scene_host->view_connected_callback_ .is_empty ()) {
113
141
InvokeDartClosure (scene_host->view_connected_callback_ );
114
142
}
115
143
}
116
144
117
145
void SceneHost::OnViewDisconnected (scenic::ResourceId id) {
118
- auto * scene_host = GetSceneHost (id);
146
+ auto * scene_host = GetSceneHostForCurrentIsolate (id);
119
147
120
148
if (scene_host && !scene_host->view_disconnected_callback_ .is_empty ()) {
121
149
InvokeDartClosure (scene_host->view_disconnected_callback_ );
122
150
}
123
151
}
124
152
125
153
void SceneHost::OnViewStateChanged (scenic::ResourceId id, bool state) {
126
- auto * scene_host = GetSceneHost (id);
154
+ auto * scene_host = GetSceneHostForCurrentIsolate (id);
127
155
128
156
if (scene_host && !scene_host->view_state_changed_callback_ .is_empty ()) {
129
157
InvokeDartFunction (scene_host->view_state_changed_callback_ , state);
@@ -138,6 +166,7 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
138
166
UIDartState::Current ()->GetTaskRunners().GetGPUTaskRunner()),
139
167
koid_(GetKoid(viewHolderToken->handle ())) {
140
168
auto dart_state = UIDartState::Current ();
169
+ isolate_service_id_ = Dart_IsolateServiceId (Dart_CurrentIsolate ());
141
170
142
171
// Initialize callbacks it they are non-null in Dart.
143
172
if (!Dart_IsNull (viewConnectedCallback)) {
@@ -152,12 +181,11 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
152
181
153
182
// This callback will be posted as a task when the |scenic::ViewHolder|
154
183
// resource is created and given an id by the GPU thread.
155
- auto bind_callback = [scene_host = this ](scenic::ResourceId id) {
156
- auto * bindings = tls_scene_host_bindings.get ();
157
- FML_DCHECK (bindings);
158
- FML_DCHECK (bindings->find (id) == bindings->end ());
159
-
160
- bindings->emplace (std::make_pair (id, scene_host));
184
+ auto bind_callback = [scene_host = this ,
185
+ isolate_service_id =
186
+ isolate_service_id_](scenic::ResourceId id) {
187
+ const auto key = SceneHostBindingKey (id, isolate_service_id);
188
+ scene_host_bindings.emplace (std::make_pair (key, scene_host));
161
189
};
162
190
163
191
// Pass the raw handle to the GPU thead; destroying a |zircon::dart::Handle|
@@ -175,9 +203,7 @@ SceneHost::SceneHost(fml::RefPtr<zircon::dart::Handle> viewHolderToken,
175
203
}
176
204
177
205
SceneHost::~SceneHost () {
178
- auto * bindings = tls_scene_host_bindings.get ();
179
- FML_DCHECK (bindings);
180
- bindings->erase (koid_);
206
+ scene_host_bindings.erase (SceneHostBindingKey (koid_, isolate_service_id_));
181
207
182
208
gpu_task_runner_->PostTask (
183
209
[id = koid_]() { flutter::ViewHolder::Destroy (id); });
0 commit comments