| From 225f21f660b943ff9ade13b0d114e8ba3b3036d5 Mon Sep 17 00:00:00 2001 |
| From: Luis Hector Chavez <lhchavez@google.com> |
| Date: Fri, 20 Jul 2018 09:39:22 -0700 |
| Subject: [PATCH] Mojo: Add a way to create thread-safe interfaces in Java |
| |
| This change adds Interface.Manager.buildThreadSafeProxy(), which is |
| roughly analogous to mojo::ThreadSafeInterfacePtr<T>. Given that Java |
| does not have move-only semantics, the Proxy object that is passed is |
| unbound and a new object is returned. |
| |
| Bug: 810084 |
| Test: cheets_ContainerSmokeTest in Chrome OS |
| Change-Id: I6565f9e526e3fa8f8cb222cb8cd11e95bb57f7d3 |
| Reviewed-on: https://chromium-review.googlesource.com/1147320 |
| Reviewed-by: Ken Rockot <rockot@chromium.org> |
| Commit-Queue: Luis Hector Chavez <lhchavez@chromium.org> |
| Cr-Commit-Position: refs/heads/master@{#577429} |
| --- |
| .../org/chromium/mojo/bindings/Interface.java | 88 +++++++++++++++++++ |
| 1 file changed, 88 insertions(+) |
| |
| diff --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 |
| index e3be8b3..f7d3f80 100644 |
| --- a/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java |
| +++ b/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java |
| @@ -20,6 +20,7 @@ import org.chromium.mojo.system.MojoException; |
| import org.chromium.mojo.system.Pair; |
| |
| import java.io.Closeable; |
| +import java.util.concurrent.Executor; |
| |
| /** |
| * Base class for mojo generated interfaces. |
| @@ -317,6 +318,67 @@ public interface Interface extends ConnectionErrorHandler, Closeable { |
| |
| } |
| |
| + /** |
| + * A {@link MessageReceiverWithResponder} implementation that forwards all calls to the thread |
| + * the ThreadSafeForwarder was created. |
| + */ |
| + class ThreadSafeForwarder implements MessageReceiverWithResponder { |
| + |
| + /** |
| + * The {@link MessageReceiverWithResponder} that will receive a serialized message for |
| + * each method call. |
| + */ |
| + private final MessageReceiverWithResponder mMessageReceiver; |
| + |
| + /** |
| + * The {@link Executor} to forward all tasks to. |
| + */ |
| + private final Executor mExecutor; |
| + |
| + /** |
| + * Constructor. |
| + * |
| + * @param core the Core implementation used to create pipes and access the async waiter. |
| + * @param messageReceiver the message receiver to send message to. |
| + */ |
| + public ThreadSafeForwarder(Core core, MessageReceiverWithResponder messageReceiver) { |
| + mMessageReceiver = messageReceiver; |
| + mExecutor = ExecutorFactory.getExecutorForCurrentThread(core); |
| + } |
| + |
| + /** |
| + * @see org.chromium.mojo.bindings.MessageReceiver#close() |
| + */ |
| + @Override |
| + public void close() { |
| + mExecutor.execute(() -> { |
| + mMessageReceiver.close(); |
| + }); |
| + } |
| + |
| + /** |
| + * @see org.chromium.mojo.bindings.MessageReceiver#accept() |
| + */ |
| + @Override |
| + public boolean accept(Message message) { |
| + mExecutor.execute(() -> { |
| + mMessageReceiver.accept(message); |
| + }); |
| + return true; |
| + } |
| + |
| + /** |
| + * @see org.chromium.mojo.bindings.MessageReceiverWithResponder#acceptWithResponder() |
| + */ |
| + @Override |
| + public boolean acceptWithResponder(Message message, MessageReceiver responder) { |
| + mExecutor.execute(() -> { |
| + mMessageReceiver.acceptWithResponder(message, responder); |
| + }); |
| + return true; |
| + } |
| + } |
| + |
| /** |
| * The |Manager| object enables building of proxies and stubs for a given interface. |
| * |
| @@ -385,6 +447,32 @@ public interface Interface extends ConnectionErrorHandler, Closeable { |
| return new InterfaceRequest<I>(handle); |
| } |
| |
| + /** |
| + * Constructs a thread-safe Proxy forwarding the calls to the given message receiver. |
| + * All calls can be performed from any thread and are posted to the {@link Executor} that |
| + * is associated with the thread on which this method was called on. |
| + * |
| + * The original Proxy object is unbound. |
| + */ |
| + public final P buildThreadSafeProxy(P proxy) { |
| + HandlerImpl handlerImpl = (HandlerImpl) proxy.getProxyHandler(); |
| + Core core = handlerImpl.getCore(); |
| + int version = handlerImpl.getVersion(); |
| + |
| + Router router = new RouterImpl(handlerImpl.passHandle()); |
| + // Close the original proxy now that its handle has been passed. |
| + proxy.close(); |
| + |
| + proxy = buildProxy( |
| + core, new ThreadSafeForwarder(core, new AutoCloseableRouter(core, router))); |
| + DelegatingConnectionErrorHandler handlers = new DelegatingConnectionErrorHandler(); |
| + handlers.addConnectionErrorHandler(proxy); |
| + router.setErrorHandler(handlers); |
| + router.start(); |
| + ((HandlerImpl) proxy.getProxyHandler()).setVersion(version); |
| + return proxy; |
| + } |
| + |
| /** |
| * Binds the implementation to the given |router|. |
| */ |
| -- |
| 2.19.0.605.g01d371f741-goog |
| |