Home | History | Annotate | Download | only in patch
      1 From 225f21f660b943ff9ade13b0d114e8ba3b3036d5 Mon Sep 17 00:00:00 2001
      2 From: Luis Hector Chavez <lhchavez (a] google.com>
      3 Date: Fri, 20 Jul 2018 09:39:22 -0700
      4 Subject: [PATCH] Mojo: Add a way to create thread-safe interfaces in Java
      5 
      6 This change adds Interface.Manager.buildThreadSafeProxy(), which is
      7 roughly analogous to mojo::ThreadSafeInterfacePtr<T>. Given that Java
      8 does not have move-only semantics, the Proxy object that is passed is
      9 unbound and a new object is returned.
     10 
     11 Bug: 810084
     12 Test: cheets_ContainerSmokeTest in Chrome OS
     13 Change-Id: I6565f9e526e3fa8f8cb222cb8cd11e95bb57f7d3
     14 Reviewed-on: https://chromium-review.googlesource.com/1147320
     15 Reviewed-by: Ken Rockot <rockot (a] chromium.org>
     16 Commit-Queue: Luis Hector Chavez <lhchavez (a] chromium.org>
     17 Cr-Commit-Position: refs/heads/master@{#577429}
     18 ---
     19  .../org/chromium/mojo/bindings/Interface.java | 88 +++++++++++++++++++
     20  1 file changed, 88 insertions(+)
     21 
     22 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
     23 index 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 -- 
    136 2.19.0.605.g01d371f741-goog
    137 
    138