Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 42afb1a

Browse files
authored
[dart:zircon] Porting Cache re-usable handle wait objects (#10809)
Change-Id: I230601acf5de24765737ad81b595fef2c154134c
1 parent 1b28752 commit 42afb1a

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle.cc

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,29 @@ namespace dart {
1616

1717
IMPLEMENT_WRAPPERTYPEINFO(zircon, Handle);
1818

19-
Handle::Handle(zx_handle_t handle) : handle_(handle) {}
19+
Handle::Handle(zx_handle_t handle) : handle_(handle) {
20+
tonic::DartState* state = tonic::DartState::Current();
21+
FML_DCHECK(state);
22+
Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon"));
23+
FML_DCHECK(!tonic::LogIfError(zircon_lib));
24+
25+
Dart_Handle on_wait_completer_type =
26+
Dart_GetClass(zircon_lib, ToDart("_OnWaitCompleteClosure"));
27+
FML_DCHECK(!tonic::LogIfError(on_wait_completer_type));
28+
on_wait_completer_type_.Set(state, on_wait_completer_type);
29+
30+
Dart_Handle async_lib = Dart_LookupLibrary(ToDart("dart:async"));
31+
FML_DCHECK(!tonic::LogIfError(async_lib));
32+
async_lib_.Set(state, async_lib);
33+
34+
Dart_Handle closure_string = ToDart("_closure");
35+
FML_DCHECK(!tonic::LogIfError(closure_string));
36+
closure_string_.Set(state, closure_string);
37+
38+
Dart_Handle schedule_microtask_string = ToDart("scheduleMicrotask");
39+
FML_DCHECK(!tonic::LogIfError(schedule_microtask_string));
40+
schedule_microtask_string_.Set(state, schedule_microtask_string);
41+
}
2042

2143
Handle::~Handle() {
2244
if (is_valid()) {
@@ -93,6 +115,36 @@ Dart_Handle Handle::Duplicate(uint32_t rights) {
93115
return ToDart(Create(out_handle));
94116
}
95117

118+
void Handle::ScheduleCallback(tonic::DartPersistentValue callback,
119+
zx_status_t status,
120+
const zx_packet_signal_t* signal) {
121+
auto state = callback.dart_state().lock();
122+
FML_DCHECK(state);
123+
tonic::DartState::Scope scope(state);
124+
125+
// Make a new _OnWaitCompleteClosure(callback, status, signal->observed).
126+
FML_DCHECK(!callback.is_empty());
127+
std::vector<Dart_Handle> constructor_args{callback.Release(), ToDart(status),
128+
ToDart(signal->observed)};
129+
Dart_Handle on_wait_complete_closure =
130+
Dart_New(on_wait_completer_type_.Get(), Dart_Null(),
131+
constructor_args.size(), constructor_args.data());
132+
FML_DCHECK(!tonic::LogIfError(on_wait_complete_closure));
133+
134+
// The _callback field contains the thunk:
135+
// () => callback(status, signal->observed)
136+
Dart_Handle closure =
137+
Dart_GetField(on_wait_complete_closure, closure_string_.Get());
138+
FML_DCHECK(!tonic::LogIfError(closure));
139+
140+
// Put the thunk on the microtask queue by calling scheduleMicrotask().
141+
std::vector<Dart_Handle> sm_args{closure};
142+
Dart_Handle sm_result =
143+
Dart_Invoke(async_lib_.Get(), schedule_microtask_string_.Get(),
144+
sm_args.size(), sm_args.data());
145+
FML_DCHECK(!tonic::LogIfError(sm_result));
146+
}
147+
96148
// clang-format: off
97149

98150
#define FOR_EACH_STATIC_BINDING(V) V(Handle, CreateInvalid)

shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class Handle : public fml::RefCountedThreadSafe<Handle>,
6060

6161
Dart_Handle Duplicate(uint32_t rights);
6262

63+
void ScheduleCallback(tonic::DartPersistentValue callback,
64+
zx_status_t status,
65+
const zx_packet_signal_t* signal);
66+
6367
private:
6468
explicit Handle(zx_handle_t handle);
6569

@@ -70,6 +74,13 @@ class Handle : public fml::RefCountedThreadSafe<Handle>,
7074
zx_handle_t handle_;
7175

7276
std::vector<HandleWaiter*> waiters_;
77+
78+
// Some cached persistent handles to make running handle wait completers
79+
// faster.
80+
tonic::DartPersistentValue async_lib_;
81+
tonic::DartPersistentValue closure_string_;
82+
tonic::DartPersistentValue on_wait_completer_type_;
83+
tonic::DartPersistentValue schedule_microtask_string_;
7384
};
7485

7586
} // namespace dart

shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle_waiter.cc

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,11 @@ void HandleWaiter::OnWaitComplete(async_dispatcher_t* dispatcher,
8181
// Remove this waiter from the handle.
8282
handle_->ReleaseWaiter(this);
8383

84+
// Schedule the callback on the microtask queue.
85+
handle_->ScheduleCallback(std::move(callback_), status, signal);
86+
8487
// Clear handle_.
8588
handle_ = nullptr;
86-
87-
auto state = callback_.dart_state().lock();
88-
FML_DCHECK(state);
89-
DartState::Scope scope(state);
90-
91-
std::vector<Dart_Handle> args{ToDart(status), ToDart(signal->observed)};
92-
FML_DCHECK(!callback_.is_empty());
93-
Dart_Handle result =
94-
Dart_InvokeClosure(callback_.Release(), args.size(), args.data());
95-
// If there was an uncaught error from the callback propagate it out.
96-
if (tonic::LogIfError(result)) {
97-
state->message_handler().UnhandledError(result);
98-
}
9989
}
10090

10191
} // namespace dart

0 commit comments

Comments
 (0)