[flutter] Port: Run handle wait completers on the microtask queue (#11649)

Change-Id: I66c39d9ef7d534094148212940eef45754559d04
This commit is contained in:
Kaushik Iska
2019-08-28 14:02:11 -07:00
committed by GitHub
parent f52c0b9270
commit 9d61b9a31a
2 changed files with 46 additions and 3 deletions
@@ -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
}
@@ -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<Dart_Handle> 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<Dart_Handle> 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