• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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