Flutter Engine
handle.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "handle.h"
6 
7 #include <algorithm>
8 
11 
12 using tonic::ToDart;
13 
14 namespace zircon {
15 namespace dart {
16 
18 
19 Handle::Handle(zx_handle_t handle) : handle_(handle) {
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 }
42 
44  if (is_valid()) {
45  zx_status_t status = Close();
46  FML_DCHECK(status == ZX_OK);
47  }
48 }
49 
50 fml::RefPtr<Handle> Handle::Create(zx_handle_t handle) {
51  return fml::MakeRefCounted<Handle>(handle);
52 }
53 
54 Dart_Handle Handle::CreateInvalid() {
55  return ToDart(Create(ZX_HANDLE_INVALID));
56 }
57 
58 zx_handle_t Handle::ReleaseHandle() {
60 
61  zx_handle_t handle = handle_;
62  handle_ = ZX_HANDLE_INVALID;
63  while (waiters_.size()) {
64  // HandleWaiter::Cancel calls Handle::ReleaseWaiter which removes the
65  // HandleWaiter from waiters_.
66  FML_DCHECK(waiters_.back()->is_pending());
67  waiters_.back()->Cancel();
68  }
69 
70  FML_DCHECK(!is_valid());
71 
72  return handle;
73 }
74 
75 zx_status_t Handle::Close() {
76  if (is_valid()) {
77  zx_handle_t handle = ReleaseHandle();
78  return zx_handle_close(handle);
79  }
80  return ZX_ERR_BAD_HANDLE;
81 }
82 
84  Dart_Handle callback) {
85  if (!is_valid()) {
86  FML_LOG(WARNING) << "Attempt to wait on an invalid handle.";
87  return nullptr;
88  }
89 
91  HandleWaiter::Create(this, signals, callback);
92  waiters_.push_back(waiter.get());
93 
94  return waiter;
95 }
96 
98  FML_DCHECK(waiter);
99  auto iter = std::find(waiters_.cbegin(), waiters_.cend(), waiter);
100  FML_DCHECK(iter != waiters_.cend());
101  FML_DCHECK(*iter == waiter);
102  waiters_.erase(iter);
103 }
104 
105 Dart_Handle Handle::Duplicate(uint32_t rights) {
106  if (!is_valid()) {
107  return ToDart(Create(ZX_HANDLE_INVALID));
108  }
109 
110  zx_handle_t out_handle;
111  zx_status_t status = zx_handle_duplicate(handle_, rights, &out_handle);
112  if (status != ZX_OK) {
113  return ToDart(Create(ZX_HANDLE_INVALID));
114  }
115  return ToDart(Create(out_handle));
116 }
117 
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 
148 // clang-format: off
149 
150 #define FOR_EACH_STATIC_BINDING(V) V(Handle, CreateInvalid)
151 
152 #define FOR_EACH_BINDING(V) \
153  V(Handle, handle) \
154  V(Handle, koid) \
155  V(Handle, is_valid) \
156  V(Handle, Close) \
157  V(Handle, AsyncWait) \
158  V(Handle, Duplicate)
159 
160 // clang-format: on
161 
162 // Tonic is missing a comma.
163 #define DART_REGISTER_NATIVE_STATIC_(CLASS, METHOD) \
164  DART_REGISTER_NATIVE_STATIC(CLASS, METHOD),
165 
168 
169 void Handle::RegisterNatives(tonic::DartLibraryNatives* natives) {
172 }
173 
174 } // namespace dart
175 } // namespace zircon
zx_handle_t ReleaseHandle()
Definition: handle.cc:58
static Dart_Handle CreateInvalid()
Definition: handle.cc:54
Definition: handle.cc:14
void ReleaseWaiter(HandleWaiter *waiter)
Definition: handle.cc:97
zx_handle_t handle() const
Definition: handle.h:52
#define FML_DCHECK(condition)
Definition: logging.h:86
fml::RefPtr< HandleWaiter > AsyncWait(zx_signals_t signals, Dart_Handle callback)
Definition: handle.cc:83
bool is_valid() const
Definition: handle.h:50
zx_status_t Close()
Definition: handle.cc:75
static DartState * Current()
Definition: dart_state.cc:55
#define FML_LOG(severity)
Definition: logging.h:65
void ScheduleCallback(tonic::DartPersistentValue callback, zx_status_t status, const zx_packet_signal_t *signal)
Definition: handle.cc:118
static fml::RefPtr< Handle > Create(zx_handle_t handle)
Definition: handle.cc:50
Definition: dart_vm.cc:38
static fml::RefPtr< HandleWaiter > Create(Handle *handle, zx_signals_t signals, Dart_Handle callback)
std::function< void()> closure
Definition: closure.h:14
#define DART_NATIVE_NO_UI_CHECK_CALLBACK(CLASS, METHOD)
#define DART_REGISTER_NATIVE_STATIC_(CLASS, METHOD)
Definition: handle.cc:163
const std::weak_ptr< DartState > & dart_state() const
#define FOR_EACH_STATIC_BINDING(V)
Definition: handle.cc:150
T * get() const
Definition: ref_ptr.h:112
#define FOR_EACH_BINDING(V)
Definition: handle.cc:152
#define DART_NATIVE_CALLBACK_STATIC(CLASS, METHOD)
Dart_Handle Duplicate(uint32_t rights)
Definition: handle.cc:105
IMPLEMENT_WRAPPERTYPEINFO(zircon, Handle)
static void RegisterNatives(tonic::DartLibraryNatives *natives)
Definition: handle.cc:169
#define DART_REGISTER_NATIVE(CLASS, METHOD)
Dart_Handle ToDart(const T &object)
bool LogIfError(Dart_Handle handle)
Definition: dart_error.cc:15