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

Side by Side Diff: mojo/public/java/bindings/src/org/chromium/mojo/bindings/RouterImpl.java

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 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
(Empty)
1 // Copyright 2014 The Chromium 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 package org.chromium.mojo.bindings;
6
7 import org.chromium.mojo.system.AsyncWaiter;
8 import org.chromium.mojo.system.Core;
9 import org.chromium.mojo.system.MessagePipeHandle;
10
11 import java.util.HashMap;
12 import java.util.Map;
13 import java.util.concurrent.Executor;
14
15 /**
16 * Implementation of {@link Router}.
17 */
18 public class RouterImpl implements Router {
19
20 /**
21 * {@link MessageReceiver} used as the {@link Connector} callback.
22 */
23 private class HandleIncomingMessageThunk implements MessageReceiver {
24
25 /**
26 * @see MessageReceiver#accept(Message)
27 */
28 @Override
29 public boolean accept(Message message) {
30 return handleIncomingMessage(message);
31 }
32
33 /**
34 * @see MessageReceiver#close()
35 */
36 @Override
37 public void close() {
38 handleConnectorClose();
39 }
40
41 }
42
43 /**
44 *
45 * {@link MessageReceiver} used to return responses to the caller.
46 */
47 class ResponderThunk implements MessageReceiver {
48 private boolean mAcceptWasInvoked = false;
49
50 /**
51 * @see
52 * MessageReceiver#accept(Message)
53 */
54 @Override
55 public boolean accept(Message message) {
56 mAcceptWasInvoked = true;
57 return RouterImpl.this.accept(message);
58 }
59
60 /**
61 * @see MessageReceiver#close()
62 */
63 @Override
64 public void close() {
65 RouterImpl.this.close();
66 }
67
68 @Override
69 protected void finalize() throws Throwable {
70 if (!mAcceptWasInvoked) {
71 // We close the pipe here as a way of signaling to the calling a pplication that an
72 // error condition occurred. Without this the calling applicatio n would have no
73 // way of knowing it should stop waiting for a response.
74 RouterImpl.this.closeOnHandleThread();
75 }
76 super.finalize();
77 }
78 }
79
80 /**
81 * The {@link Connector} which is connected to the handle.
82 */
83 private final Connector mConnector;
84
85 /**
86 * The {@link MessageReceiverWithResponder} that will consume the messages r eceived from the
87 * pipe.
88 */
89 private MessageReceiverWithResponder mIncomingMessageReceiver;
90
91 /**
92 * The next id to use for a request id which needs a response. It is auto-in cremented.
93 */
94 private long mNextRequestId = 1;
95
96 /**
97 * The map from request ids to {@link MessageReceiver} of request currently in flight.
98 */
99 private Map<Long, MessageReceiver> mResponders = new HashMap<Long, MessageRe ceiver>();
100
101 /**
102 * An Executor that will run on the thread associated with the MessagePipe t o which
103 * this Router is bound. This may be {@code Null} if the MessagePipeHandle p assed
104 * in to the constructor is not valid.
105 */
106 private final Executor mExecutor;
107
108 /**
109 * Constructor that will use the default {@link AsyncWaiter}.
110 *
111 * @param messagePipeHandle The {@link MessagePipeHandle} to route message f or.
112 */
113 public RouterImpl(MessagePipeHandle messagePipeHandle) {
114 this(messagePipeHandle, BindingsHelper.getDefaultAsyncWaiterForHandle(me ssagePipeHandle));
115 }
116
117 /**
118 * Constructor.
119 *
120 * @param messagePipeHandle The {@link MessagePipeHandle} to route message f or.
121 * @param asyncWaiter the {@link AsyncWaiter} to use to get notification of new messages on the
122 * handle.
123 */
124 public RouterImpl(MessagePipeHandle messagePipeHandle, AsyncWaiter asyncWait er) {
125 mConnector = new Connector(messagePipeHandle, asyncWaiter);
126 mConnector.setIncomingMessageReceiver(new HandleIncomingMessageThunk());
127 Core core = messagePipeHandle.getCore();
128 if (core != null) {
129 mExecutor = ExecutorFactory.getExecutorForCurrentThread(core);
130 } else {
131 mExecutor = null;
132 }
133 }
134
135 /**
136 * @see org.chromium.mojo.bindings.Router#start()
137 */
138 @Override
139 public void start() {
140 mConnector.start();
141 }
142
143 /**
144 * @see Router#setIncomingMessageReceiver(MessageReceiverWithResponder)
145 */
146 @Override
147 public void setIncomingMessageReceiver(MessageReceiverWithResponder incoming MessageReceiver) {
148 this.mIncomingMessageReceiver = incomingMessageReceiver;
149 }
150
151 /**
152 * @see MessageReceiver#accept(Message)
153 */
154 @Override
155 public boolean accept(Message message) {
156 // A message without responder is directly forwarded to the connector.
157 return mConnector.accept(message);
158 }
159
160 /**
161 * @see MessageReceiverWithResponder#acceptWithResponder(Message, MessageRec eiver)
162 */
163 @Override
164 public boolean acceptWithResponder(Message message, MessageReceiver responde r) {
165 // The message must have a header.
166 ServiceMessage messageWithHeader = message.asServiceMessage();
167 // Checking the message expects a response.
168 assert messageWithHeader.getHeader().hasFlag(MessageHeader.MESSAGE_EXPEC TS_RESPONSE_FLAG);
169
170 // Compute a request id for being able to route the response.
171 long requestId = mNextRequestId++;
172 // Reserve 0 in case we want it to convey special meaning in the future.
173 if (requestId == 0) {
174 requestId = mNextRequestId++;
175 }
176 if (mResponders.containsKey(requestId)) {
177 throw new IllegalStateException("Unable to find a new request identi fier.");
178 }
179 messageWithHeader.setRequestId(requestId);
180 mResponders.put(requestId, responder);
181 if (!mConnector.accept(messageWithHeader)) {
182 // Only keep the responder is the message has been accepted.
183 mResponders.remove(requestId);
184 return false;
185 }
186 return true;
187 }
188
189 /**
190 * @see org.chromium.mojo.bindings.HandleOwner#passHandle()
191 */
192 @Override
193 public MessagePipeHandle passHandle() {
194 return mConnector.passHandle();
195 }
196
197 /**
198 * @see java.io.Closeable#close()
199 */
200 @Override
201 public void close() {
202 mConnector.close();
203 }
204
205 /**
206 * @see Router#setErrorHandler(ConnectionErrorHandler)
207 */
208 @Override
209 public void setErrorHandler(ConnectionErrorHandler errorHandler) {
210 mConnector.setErrorHandler(errorHandler);
211 }
212
213 /**
214 * Receive a message from the connector. Returns |true| if the message has b een handled.
215 */
216 private boolean handleIncomingMessage(Message message) {
217 MessageHeader header = message.asServiceMessage().getHeader();
218 if (header.hasFlag(MessageHeader.MESSAGE_EXPECTS_RESPONSE_FLAG)) {
219 if (mIncomingMessageReceiver != null) {
220 return mIncomingMessageReceiver.acceptWithResponder(message, new ResponderThunk());
221 }
222 // If we receive a request expecting a response when the client is n ot
223 // listening, then we have no choice but to tear down the pipe.
224 close();
225 return false;
226 } else if (header.hasFlag(MessageHeader.MESSAGE_IS_RESPONSE_FLAG)) {
227 long requestId = header.getRequestId();
228 MessageReceiver responder = mResponders.get(requestId);
229 if (responder == null) {
230 return false;
231 }
232 mResponders.remove(requestId);
233 return responder.accept(message);
234 } else {
235 if (mIncomingMessageReceiver != null) {
236 return mIncomingMessageReceiver.accept(message);
237 }
238 // OK to drop the message.
239 }
240 return false;
241 }
242
243 private void handleConnectorClose() {
244 if (mIncomingMessageReceiver != null) {
245 mIncomingMessageReceiver.close();
246 }
247 }
248
249 /**
250 * Invokes {@link #close()} asynchronously on the thread associated with
251 * this Router's Handle. If this Router was constructed with an invalid
252 * handle then this method does nothing.
253 */
254 private void closeOnHandleThread() {
255 if (mExecutor != null) {
256 mExecutor.execute(new Runnable() {
257
258 @Override
259 public void run() {
260 close();
261 }
262 });
263 }
264 }
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698