blob: 825c818e5c9505b148662f827ef32b015b8ab50b [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "dart-pkg/zircon/sdk_ext/handle_waiter.h"
#include <lib/async/default.h>
#include "dart-pkg/zircon/sdk_ext/handle.h"
#include "src/lib/fxl/logging.h"
#include "third_party/dart/runtime/include/dart_api.h"
#include "third_party/tonic/converter/dart_converter.h"
#include "third_party/tonic/dart_args.h"
#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;
using tonic::DartState;
using tonic::ToDart;
namespace zircon {
namespace dart {
IMPLEMENT_WRAPPERTYPEINFO(zircon, HandleWaiter);
#define FOR_EACH_BINDING(V) V(HandleWaiter, Cancel)
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
void HandleWaiter::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
fxl::RefPtr<HandleWaiter> HandleWaiter::Create(Handle* handle,
zx_signals_t signals,
Dart_Handle callback) {
return fxl::MakeRefCounted<HandleWaiter>(handle, signals, callback);
}
HandleWaiter::HandleWaiter(Handle* handle, zx_signals_t signals,
Dart_Handle callback)
: wait_(this, handle->handle(), signals),
handle_(handle),
callback_(DartState::Current(), callback) {
FXL_CHECK(handle_ != nullptr);
FXL_CHECK(handle_->is_valid());
zx_status_t status = wait_.Begin(async_get_default_dispatcher());
FXL_DCHECK(status == ZX_OK);
}
HandleWaiter::~HandleWaiter() { Cancel(); }
void HandleWaiter::Cancel() {
FXL_DCHECK(wait_.is_pending() == !!handle_);
if (handle_) {
// Cancel the wait.
wait_.Cancel();
// Release this object from the handle and clear handle_.
handle_->ReleaseWaiter(this);
handle_ = nullptr;
}
FXL_DCHECK(!wait_.is_pending());
}
void HandleWaiter::OnWaitComplete(async_dispatcher_t* dispatcher,
async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal) {
FXL_DCHECK(handle_);
FXL_DCHECK(!callback_.is_empty());
// Hold a reference to this object.
fxl::RefPtr<HandleWaiter> ref(this);
// 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;
}
} // namespace dart
} // namespace zircon