Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: mojo/public/java/bindings/src/org/chromium/mojo/bindings/ExecutorFactory.java

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.mojo.bindings;
6
7 import org.chromium.mojo.system.AsyncWaiter;
8 import org.chromium.mojo.system.AsyncWaiter.Callback;
9 import org.chromium.mojo.system.Core;
10 import org.chromium.mojo.system.MessagePipeHandle;
11 import org.chromium.mojo.system.MessagePipeHandle.ReadMessageResult;
12 import org.chromium.mojo.system.MojoException;
13 import org.chromium.mojo.system.MojoResult;
14 import org.chromium.mojo.system.Pair;
15 import org.chromium.mojo.system.ResultAnd;
16
17 import java.nio.ByteBuffer;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.concurrent.Executor;
21
22 /**
23 * A factory which provides per-thread executors, which enable execution on the thread from which
24 * they were obtained.
25 */
26 class ExecutorFactory {
27
28 /**
29 * A null buffer which is used to send messages without any data on the Pipe dExecutor's
30 * signaling handles.
31 */
32 private static final ByteBuffer NOTIFY_BUFFER = null;
33
34 /**
35 * Implementation of the executor which uses a pair of {@link MessagePipeHan dle} for signaling.
36 * The executor will wait asynchronously on one end of a {@link MessagePipeH andle} on the thread
37 * on which it was created. Other threads can call execute with a {@link Run nable}, and the
38 * executor will queue the {@link Runnable} and write a message on the other end of the handle.
39 * This will wake up the executor which is waiting on the handle, which will then dequeue the
40 * {@link Runnable} and execute it on the original thread.
41 */
42 private static class PipedExecutor implements Executor, Callback {
43
44 /**
45 * The handle which is written to. Access to this object must be protect ed with |mLock|.
46 */
47 private final MessagePipeHandle mWriteHandle;
48 /**
49 * The handle which is read from.
50 */
51 private final MessagePipeHandle mReadHandle;
52 /**
53 * The list of actions left to be run. Access to this object must be pro tected with |mLock|.
54 */
55 private final List<Runnable> mPendingActions;
56 /**
57 * Lock protecting access to |mWriteHandle| and |mPendingActions|.
58 */
59 private final Object mLock;
60 /**
61 * The {@link AsyncWaiter} to get notified of new message availability o n |mReadHandle|.
62 */
63 private final AsyncWaiter mWaiter;
64
65 /**
66 * Constructor.
67 */
68 public PipedExecutor(Core core) {
69 mWaiter = core.getDefaultAsyncWaiter();
70 assert mWaiter != null;
71 mLock = new Object();
72 Pair<MessagePipeHandle, MessagePipeHandle> handles = core.createMess agePipe(
73 new MessagePipeHandle.CreateOptions());
74 mReadHandle = handles.first;
75 mWriteHandle = handles.second;
76 mPendingActions = new ArrayList<Runnable>();
77 asyncWait();
78 }
79
80 /**
81 * Asynchronously wait for the next command to arrive. This should only be called on the
82 * executor thread.
83 */
84 private void asyncWait() {
85 mWaiter.asyncWait(mReadHandle, Core.HandleSignals.READABLE, Core.DEA DLINE_INFINITE,
86 this);
87 }
88
89 /**
90 * @see Callback#onResult(int)
91 */
92 @Override
93 public void onResult(int result) {
94 if (result == MojoResult.OK && readNotifyBufferMessage()) {
95 runNextAction();
96 } else {
97 close();
98 }
99 }
100
101 /**
102 * @see Callback#onError(MojoException)
103 */
104 @Override
105 public void onError(MojoException exception) {
106 close();
107 }
108
109 /**
110 * Close the handles. Should only be called on the executor thread.
111 */
112 private void close() {
113 synchronized (mLock) {
114 mWriteHandle.close();
115 mPendingActions.clear();
116 }
117 mReadHandle.close();
118 }
119
120 /**
121 * Read the next message on |mReadHandle|, and return |true| if successf ul, |false|
122 * otherwise.
123 */
124 private boolean readNotifyBufferMessage() {
125 try {
126 ResultAnd<ReadMessageResult> readMessageResult =
127 mReadHandle.readMessage(NOTIFY_BUFFER, 0, MessagePipeHan dle.ReadFlags.NONE);
128 if (readMessageResult.getMojoResult() == MojoResult.OK) {
129 asyncWait();
130 return true;
131 }
132 } catch (MojoException e) {
133 // Will be closed by the fall back at the end of this method.
134 }
135 return false;
136 }
137
138 /**
139 * Run the next action in the |mPendingActions| queue.
140 */
141 private void runNextAction() {
142 Runnable toRun = null;
143 synchronized (mLock) {
144 toRun = mPendingActions.remove(0);
145 }
146 toRun.run();
147 }
148
149 /**
150 * Execute the given |command| in the executor thread. This can be calle d on any thread.
151 *
152 * @see Executor#execute(Runnable)
153 */
154 @Override
155 public void execute(Runnable command) {
156 // Accessing the write handle must be protected by the lock, because it can be closed
157 // from the executor's thread.
158 synchronized (mLock) {
159 if (!mWriteHandle.isValid()) {
160 throw new IllegalStateException(
161 "Trying to execute an action on a closed executor.") ;
162 }
163 mPendingActions.add(command);
164 mWriteHandle.writeMessage(NOTIFY_BUFFER, null, MessagePipeHandle .WriteFlags.NONE);
165 }
166 }
167 }
168
169 /**
170 * Keep one executor per executor thread.
171 */
172 private static final ThreadLocal<Executor> EXECUTORS = new ThreadLocal<Execu tor>();
173
174 /**
175 * Returns an {@link Executor} that will run all of its actions in the curre nt thread.
176 */
177 public static Executor getExecutorForCurrentThread(Core core) {
178 Executor executor = EXECUTORS.get();
179 if (executor == null) {
180 executor = new PipedExecutor(core);
181 EXECUTORS.set(executor);
182 }
183 return executor;
184 }
185 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698