From 9d61b9a31a337b0fe28c8a7561545f7678646357 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Wed, 28 Aug 2019 14:02:11 -0700 Subject: [PATCH] [flutter] Port: Run handle wait completers on the microtask queue (#11649) Change-Id: I66c39d9ef7d534094148212940eef45754559d04 --- .../dart-pkg/zircon/lib/src/handle.dart | 14 ++++++++ .../dart-pkg/zircon/sdk_ext/handle_waiter.cc | 35 +++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle.dart b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle.dart index 9702a4839f8..730689e0df0 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle.dart +++ b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle.dart @@ -39,3 +39,17 @@ class Handle extends NativeFieldWrapperClass2 { Handle duplicate(int rights) native 'Handle_Duplicate'; } + +@pragma('vm:entry-point') +class _OnWaitCompleteClosure { // ignore: unused_element + // No public constructor - this can only be created from native code. + @pragma('vm:entry-point') + _OnWaitCompleteClosure(this._callback, this._arg1, this._arg2); + + Function _callback; + Object _arg1; + Object _arg2; + + @pragma('vm:entry-point') + Function get _closure => () => _callback(_arg1, _arg2); // ignore: unused_element +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle_waiter.cc b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle_waiter.cc index 8c1be48e178..79327f59527 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle_waiter.cc +++ b/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle_waiter.cc @@ -12,6 +12,7 @@ #include "third_party/tonic/dart_binding_macros.h" #include "third_party/tonic/dart_library_natives.h" #include "third_party/tonic/dart_message_handler.h" +#include "third_party/tonic/dart_microtask_queue.h" #include "third_party/tonic/logging/dart_invoke.h" using tonic::DartInvokeField; @@ -81,11 +82,39 @@ void HandleWaiter::OnWaitComplete(async_dispatcher_t* dispatcher, // Remove this waiter from the handle. handle_->ReleaseWaiter(this); - // Schedule the callback on the microtask queue. - handle_->ScheduleCallback(std::move(callback_), status, signal); - // Clear handle_. handle_ = nullptr; + + auto state = callback_.dart_state().lock(); + FML_DCHECK(state); + DartState::Scope scope(state); + + // Put the closure invocation on the microtask queue. + Dart_Handle zircon_lib = Dart_LookupLibrary(ToDart("dart:zircon")); + FML_DCHECK(!tonic::LogIfError(zircon_lib)); + + Dart_Handle owc_type = + Dart_GetClass(zircon_lib, ToDart("_OnWaitCompleteClosure")); + FML_DCHECK(!tonic::LogIfError(owc_type)); + + FML_DCHECK(!callback_.is_empty()); + std::vector owc_args{callback_.Release(), ToDart(status), + ToDart(signal->observed)}; + Dart_Handle owc = + Dart_New(owc_type, Dart_Null(), owc_args.size(), owc_args.data()); + FML_DCHECK(!tonic::LogIfError(owc)); + + Dart_Handle closure = Dart_GetField(owc, ToDart("_closure")); + FML_DCHECK(!tonic::LogIfError(closure)); + + // TODO(issue#tbd): Use tonic::DartMicrotaskQueue::ScheduleMicrotask() + // instead when tonic::DartState gets a microtask queue field. + Dart_Handle async_lib = Dart_LookupLibrary(ToDart("dart:async")); + FML_DCHECK(!tonic::LogIfError(async_lib)); + std::vector sm_args{closure}; + Dart_Handle sm_result = Dart_Invoke(async_lib, ToDart("scheduleMicrotask"), + sm_args.size(), sm_args.data()); + FML_DCHECK(!tonic::LogIfError(sm_result)); } } // namespace dart