1From 225f21f660b943ff9ade13b0d114e8ba3b3036d5 Mon Sep 17 00:00:00 2001 2From: Luis Hector Chavez <lhchavez@google.com> 3Date: Fri, 20 Jul 2018 09:39:22 -0700 4Subject: [PATCH] Mojo: Add a way to create thread-safe interfaces in Java 5 6This change adds Interface.Manager.buildThreadSafeProxy(), which is 7roughly analogous to mojo::ThreadSafeInterfacePtr<T>. Given that Java 8does not have move-only semantics, the Proxy object that is passed is 9unbound and a new object is returned. 10 11Bug: 810084 12Test: cheets_ContainerSmokeTest in Chrome OS 13Change-Id: I6565f9e526e3fa8f8cb222cb8cd11e95bb57f7d3 14Reviewed-on: https://chromium-review.googlesource.com/1147320 15Reviewed-by: Ken Rockot <rockot@chromium.org> 16Commit-Queue: Luis Hector Chavez <lhchavez@chromium.org> 17Cr-Commit-Position: refs/heads/master@{#577429} 18--- 19 .../org/chromium/mojo/bindings/Interface.java | 88 +++++++++++++++++++ 20 1 file changed, 88 insertions(+) 21 22diff --git a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java 23index e3be8b3..f7d3f80 100644 24--- a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java 25+++ b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java 26@@ -20,6 +20,7 @@ import org.chromium.mojo.system.MojoException; 27 import org.chromium.mojo.system.Pair; 28 29 import java.io.Closeable; 30+import java.util.concurrent.Executor; 31 32 /** 33 * Base class for mojo generated interfaces. 34@@ -317,6 +318,67 @@ public interface Interface extends ConnectionErrorHandler, Closeable { 35 36 } 37 38+ /** 39+ * A {@link MessageReceiverWithResponder} implementation that forwards all calls to the thread 40+ * the ThreadSafeForwarder was created. 41+ */ 42+ class ThreadSafeForwarder implements MessageReceiverWithResponder { 43+ 44+ /** 45+ * The {@link MessageReceiverWithResponder} that will receive a serialized message for 46+ * each method call. 47+ */ 48+ private final MessageReceiverWithResponder mMessageReceiver; 49+ 50+ /** 51+ * The {@link Executor} to forward all tasks to. 52+ */ 53+ private final Executor mExecutor; 54+ 55+ /** 56+ * Constructor. 57+ * 58+ * @param core the Core implementation used to create pipes and access the async waiter. 59+ * @param messageReceiver the message receiver to send message to. 60+ */ 61+ public ThreadSafeForwarder(Core core, MessageReceiverWithResponder messageReceiver) { 62+ mMessageReceiver = messageReceiver; 63+ mExecutor = ExecutorFactory.getExecutorForCurrentThread(core); 64+ } 65+ 66+ /** 67+ * @see org.chromium.mojo.bindings.MessageReceiver#close() 68+ */ 69+ @Override 70+ public void close() { 71+ mExecutor.execute(() -> { 72+ mMessageReceiver.close(); 73+ }); 74+ } 75+ 76+ /** 77+ * @see org.chromium.mojo.bindings.MessageReceiver#accept() 78+ */ 79+ @Override 80+ public boolean accept(Message message) { 81+ mExecutor.execute(() -> { 82+ mMessageReceiver.accept(message); 83+ }); 84+ return true; 85+ } 86+ 87+ /** 88+ * @see org.chromium.mojo.bindings.MessageReceiverWithResponder#acceptWithResponder() 89+ */ 90+ @Override 91+ public boolean acceptWithResponder(Message message, MessageReceiver responder) { 92+ mExecutor.execute(() -> { 93+ mMessageReceiver.acceptWithResponder(message, responder); 94+ }); 95+ return true; 96+ } 97+ } 98+ 99 /** 100 * The |Manager| object enables building of proxies and stubs for a given interface. 101 * 102@@ -385,6 +447,32 @@ public interface Interface extends ConnectionErrorHandler, Closeable { 103 return new InterfaceRequest<I>(handle); 104 } 105 106+ /** 107+ * Constructs a thread-safe Proxy forwarding the calls to the given message receiver. 108+ * All calls can be performed from any thread and are posted to the {@link Executor} that 109+ * is associated with the thread on which this method was called on. 110+ * 111+ * The original Proxy object is unbound. 112+ */ 113+ public final P buildThreadSafeProxy(P proxy) { 114+ HandlerImpl handlerImpl = (HandlerImpl) proxy.getProxyHandler(); 115+ Core core = handlerImpl.getCore(); 116+ int version = handlerImpl.getVersion(); 117+ 118+ Router router = new RouterImpl(handlerImpl.passHandle()); 119+ // Close the original proxy now that its handle has been passed. 120+ proxy.close(); 121+ 122+ proxy = buildProxy( 123+ core, new ThreadSafeForwarder(core, new AutoCloseableRouter(core, router))); 124+ DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler(); 125+ handlers.addConnectionErrorHandler(proxy); 126+ router.setErrorHandler(handlers); 127+ router.start(); 128+ ((HandlerImpl) proxy.getProxyHandler()).setVersion(version); 129+ return proxy; 130+ } 131+ 132 /** 133 * Binds the implementation to the given |router|. 134 */ 135-- 1362.19.0.605.g01d371f741-goog 137 138