From 23b27ba5c54bf6368980117d91bc51c4495e2c50 Mon Sep 17 00:00:00 2001 From: Luis Hector Chavez Date: Fri, 20 Jul 2018 09:39:22 -0700 Subject: Mojo: Add a way to create thread-safe interfaces in Java This change adds Interface.Manager.buildThreadSafeProxy(), which is roughly analogous to mojo::ThreadSafeInterfacePtr. Given that Java does not have move-only semantics, the Proxy object that is passed is unbound and a new object is returned. Bug: None Test: cheets_ContainerSmokeTest in Chrome OS Change-Id: I6565f9e526e3fa8f8cb222cb8cd11e95bb57f7d3 Reviewed-on: https://chromium-review.googlesource.com/1147320 Reviewed-by: Ken Rockot Commit-Queue: Luis Hector Chavez Cr-Commit-Position: refs/heads/master@{#577429} --- ...-to-create-thread-safe-interfaces-in-Java.patch | 137 +++++++++++++++++++++ .../src/org/chromium/mojo/bindings/Interface.java | 88 +++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 libchrome_tools/patch/mojo-Add-a-way-to-create-thread-safe-interfaces-in-Java.patch diff --git a/libchrome_tools/patch/mojo-Add-a-way-to-create-thread-safe-interfaces-in-Java.patch b/libchrome_tools/patch/mojo-Add-a-way-to-create-thread-safe-interfaces-in-Java.patch new file mode 100644 index 0000000000..7610293924 --- /dev/null +++ b/libchrome_tools/patch/mojo-Add-a-way-to-create-thread-safe-interfaces-in-Java.patch @@ -0,0 +1,137 @@ +From 225f21f660b943ff9ade13b0d114e8ba3b3036d5 Mon Sep 17 00:00:00 2001 +From: Luis Hector Chavez +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. 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 +Commit-Queue: Luis Hector Chavez +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(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 + 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 e3be8b3daa..f7d3f80256 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(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|. */ -- cgit v1.2.3