Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: content/common/message_port.cc

Issue 2725133002: Mojo: Armed Watchers (Closed)
Patch Set: rebase Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/common/message_port.h" 5 #include "content/common/message_port.h"
6 6
7 #include "base/bind.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/threading/thread_task_runner_handle.h"
8 10
9 namespace content { 11 namespace content {
10 12
11 MessagePort::~MessagePort() { 13 MessagePort::~MessagePort() {
12 } 14 }
13 15
14 MessagePort::MessagePort() : state_(new State()) { 16 MessagePort::MessagePort() : state_(new State()) {
15 } 17 }
16 18
17 MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) { 19 MessagePort::MessagePort(const MessagePort& other) : state_(other.state_) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 } 142 }
141 143
142 MessagePort::State::State(mojo::ScopedMessagePipeHandle handle) 144 MessagePort::State::State(mojo::ScopedMessagePipeHandle handle)
143 : handle_(std::move(handle)) { 145 : handle_(std::move(handle)) {
144 } 146 }
145 147
146 void MessagePort::State::AddWatch() { 148 void MessagePort::State::AddWatch() {
147 if (!callback_) 149 if (!callback_)
148 return; 150 return;
149 151
152 DCHECK(!watcher_handle_.is_valid());
153 MojoResult rv = CreateWatcher(&State::CallOnHandleReady, &watcher_handle_);
154 DCHECK_EQ(MOJO_RESULT_OK, rv);
155
156 // We use a scoped_refptr<State> instance as the watch context. This is owned
157 // by the watch and deleted upon receiving a cancellation notification.
158 scoped_refptr<State>* state_ref = new scoped_refptr<State>(this);
159 context_ = reinterpret_cast<uintptr_t>(state_ref);
160
150 // NOTE: An HTML MessagePort does not receive an event to tell it when the 161 // NOTE: An HTML MessagePort does not receive an event to tell it when the
151 // peer has gone away, so we only watch for readability here. 162 // peer has gone away, so we only watch for readability here.
152 MojoResult rv = MojoWatch(handle_.get().value(), 163 rv = MojoWatch(watcher_handle_.get().value(), handle_.get().value(),
153 MOJO_HANDLE_SIGNAL_READABLE, 164 MOJO_HANDLE_SIGNAL_READABLE, context_);
154 &MessagePort::State::OnHandleReady, 165 DCHECK_EQ(MOJO_RESULT_OK, rv);
155 reinterpret_cast<uintptr_t>(this)); 166
156 if (rv != MOJO_RESULT_OK) 167 ArmWatcher();
157 DVLOG(1) << this << " MojoWatch failed: " << rv;
158 } 168 }
159 169
160 void MessagePort::State::CancelWatch() { 170 void MessagePort::State::CancelWatch() {
161 if (!callback_) 171 watcher_handle_.reset();
172 context_ = 0;
173 }
174
175 MessagePort::State::~State() = default;
176
177 void MessagePort::State::ArmWatcher() {
178 if (!watcher_handle_.is_valid())
162 return; 179 return;
163 180
164 // NOTE: This synchronizes with the thread where OnHandleReady runs so we are 181 uint32_t num_ready_contexts = 1;
165 // sure to not be racing with it. 182 uintptr_t ready_context;
166 MojoCancelWatch(handle_.get().value(), reinterpret_cast<uintptr_t>(this)); 183 MojoResult ready_result;
184 MojoHandleSignalsState ready_state;
185 MojoResult rv =
186 MojoArmWatcher(watcher_handle_.get().value(), &num_ready_contexts,
187 &ready_context, &ready_result, &ready_state);
188 if (rv == MOJO_RESULT_OK)
189 return;
190
191 // The watcher could not be armed because it would notify immediately.
192 DCHECK_EQ(MOJO_RESULT_FAILED_PRECONDITION, rv);
193 DCHECK_EQ(1u, num_ready_contexts);
194 DCHECK_EQ(context_, ready_context);
195
196 if (ready_result == MOJO_RESULT_OK) {
197 // The handle is already signaled, so we trigger a callback now.
198 base::ThreadTaskRunnerHandle::Get()->PostTask(
199 FROM_HERE, base::Bind(&State::OnHandleReady, this, MOJO_RESULT_OK));
200 return;
201 }
202
203 if (ready_result == MOJO_RESULT_FAILED_PRECONDITION) {
204 DVLOG(1) << this << " MojoArmWatcher failed because of a broken pipe.";
205 return;
206 }
207
208 NOTREACHED();
167 } 209 }
168 210
169 // static 211 void MessagePort::State::OnHandleReady(MojoResult result) {
170 void MessagePort::State::OnHandleReady( 212 if (result == MOJO_RESULT_OK && callback_) {
171 uintptr_t context, 213 callback_.Run();
172 MojoResult result, 214 ArmWatcher();
173 MojoHandleSignalsState signals_state,
174 MojoWatchNotificationFlags flags) {
175 if (result == MOJO_RESULT_OK) {
176 reinterpret_cast<MessagePort::State*>(context)->callback_.Run();
177 } else { 215 } else {
178 // And now his watch is ended. 216 // And now his watch is ended.
179 } 217 }
180 } 218 }
181 219
182 MessagePort::State::~State() { 220 // static
183 CancelWatch(); 221 void MessagePort::State::CallOnHandleReady(uintptr_t context,
222 MojoResult result,
223 MojoHandleSignalsState signals_state,
224 MojoWatcherNotificationFlags flags) {
225 auto* state_ref = reinterpret_cast<scoped_refptr<State>*>(context);
226 if (result == MOJO_RESULT_CANCELLED) {
227 // Last notification. Delete the watch's owned State ref.
228 delete state_ref;
229 } else {
230 (*state_ref)->OnHandleReady(result);
231 }
184 } 232 }
185 233
186 } // namespace content 234 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698