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

Side by Side Diff: mojo/public/dart/src/handle_watcher.dart

Issue 728133002: Update mojo sdk to rev e01f9a49449381a5eb430c1fd88bf2cae73ec35a (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: android + ios gyp fixes Created 6 years, 1 month 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
« no previous file with comments | « mojo/public/dart/src/handle.dart ('k') | mojo/public/dart/src/message_pipe.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 part of core;
6
7 class _MojoHandleWatcherNatives {
8 static int sendControlData(
9 int controlHandle, int mojoHandle, SendPort port, int data)
10 native "MojoHandleWatcher_SendControlData";
11 static List recvControlData(int controlHandle)
12 native "MojoHandleWatcher_RecvControlData";
13 static int setControlHandle(int controlHandle)
14 native "MojoHandleWatcher_SetControlHandle";
15 static int getControlHandle()
16 native "MojoHandleWatcher_GetControlHandle";
17 }
18
19 // The MojoHandleWatcher sends a stream of events to application isolates that
20 // register Mojo handles with it. Application isolates make the following calls:
21 //
22 // Start() - Starts up the MojoHandleWatcher isolate. Should be called only once
23 // per VM process.
24 //
25 // Stop() - Causes the MojoHandleWatcher isolate to exit.
26 //
27 // add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add
28 // 'handle' to the set of handles it watches, and to notify the calling
29 // isolate only for the events specified by 'signals' using the send port
30 // 'port'
31 //
32 // remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle'
33 // from the set of handles it watches. This allows the application isolate
34 // to, e.g., pause the stream of events.
35 //
36 // toggleWrite(handle) - Modifies the set of signals that an application isolate
37 // wishes to be notified about. Whether the application isolate should be
38 // be notified about a handle ready for writing is made the opposite.
39 //
40 // close(handle) - Notifies the HandleWatcherIsolate that a handle it is
41 // watching should be removed from its set and closed.
42 class MojoHandleWatcher {
43 // Control commands.
44 static const int ADD = 0;
45 static const int REMOVE = 1;
46 static const int TOGGLE_WRITE = 2;
47 static const int CLOSE = 3;
48 static const int SHUTDOWN = 4;
49
50 static int _encodeCommand(int cmd, [int signals = 0]) =>
51 (cmd << 2) | (signals & MojoHandleSignals.READWRITE);
52 static int _decodeCommand(int cmd) => cmd >> 2;
53
54 // The Mojo handle over which control messages are sent.
55 int _controlHandle;
56
57 // Whether the handle watcher should shut down.
58 bool _shutdown;
59
60 // The list of handles being watched.
61 List<int> _handles;
62 int _handleCount;
63
64 // A port for each handle on which to send events back to the isolate that
65 // owns the handle.
66 List<SendPort> _ports;
67
68 // The signals that we care about for each handle.
69 List<int> _signals;
70
71 // A mapping from Mojo handles to their indices in _handles.
72 Map<int, int> _handleIndices;
73
74 // Since we are not storing wrapped handles, a dummy handle for when we need
75 // a RawMojoHandle.
76 RawMojoHandle _tempHandle;
77
78 MojoHandleWatcher(this._controlHandle) :
79 _shutdown = false,
80 _handles = new List<int>(),
81 _ports = new List<SendPort>(),
82 _signals = new List<int>(),
83 _handleIndices = new Map<int, int>(),
84 _handleCount = 1,
85 _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID) {
86 // Setup control handle.
87 _handles.add(_controlHandle);
88 _ports.add(null); // There is no port for the control handle.
89 _signals.add(MojoHandleSignals.READABLE);
90 _handleIndices[_controlHandle] = 0;
91 }
92
93 static void _handleWatcherIsolate(MojoHandleWatcher watcher) {
94 while (!watcher._shutdown) {
95 int res = RawMojoHandle.waitMany(watcher._handles,
96 watcher._signals,
97 RawMojoHandle.DEADLINE_INDEFINITE);
98 if (res == 0) {
99 watcher._handleControlMessage();
100 } else if (res > 0) {
101 int handle = watcher._handles[res];
102 // Route event.
103 watcher._routeEvent(res);
104 // Remove the handle from the list.
105 watcher._removeHandle(handle);
106 } else if (res == MojoResult.kFailedPrecondition) {
107 // None of the handles can ever be satisfied, including the control
108 // handle. This probably means we are going down. Clean up and
109 // shutdown.
110 watcher._pruneClosedHandles();
111 watcher._shutdown = true;
112 } else {
113 // Some handle was closed, but not by us.
114 // We have to go through the list and find it.
115 watcher._pruneClosedHandles();
116 }
117 }
118 }
119
120 void _routeEvent(int idx) {
121 int client_handle = _handles[idx];
122 int signals = _signals[idx];
123 SendPort port = _ports[idx];
124
125 _tempHandle.h = client_handle;
126 bool readyWrite =
127 MojoHandleSignals.isWritable(signals) && _tempHandle.readyWrite();
128 bool readyRead =
129 MojoHandleSignals.isReadable(signals) && _tempHandle.readyRead();
130 if (readyRead && readyWrite) {
131 port.send(MojoHandleSignals.READWRITE);
132 } else if (readyWrite) {
133 port.send(MojoHandleSignals.WRITABLE);
134 } else if (readyRead) {
135 port.send(MojoHandleSignals.READABLE);
136 }
137 _tempHandle.h = RawMojoHandle.INVALID;
138 }
139
140 void _handleControlMessage() {
141 List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle);
142 // result[0] = mojo handle if any
143 // result[1] = SendPort if any
144 // result[2] = command << 2 | WRITABLE | READABLE
145
146 int signals = result[2] & MojoHandleSignals.READWRITE;
147 int command = _decodeCommand(result[2]);
148 switch (command) {
149 case ADD:
150 _addHandle(result[0], result[1], signals);
151 break;
152 case REMOVE:
153 _removeHandle(result[0]);
154 break;
155 case TOGGLE_WRITE:
156 _toggleWrite(result[0]);
157 break;
158 case CLOSE:
159 _close(result[0]);
160 break;
161 case SHUTDOWN:
162 _shutdown = true;
163 break;
164 default:
165 throw new Exception("Invalid Command: $command");
166 break;
167 }
168 }
169
170 void _addHandle(int mojoHandle, SendPort port, int signals) {
171 _handles.add(mojoHandle);
172 _ports.add(port);
173 _signals.add(signals & MojoHandleSignals.READWRITE);
174 _handleIndices[mojoHandle] = _handleCount;
175 _handleCount++;
176 }
177
178 void _removeHandle(int mojoHandle) {
179 int idx = _handleIndices[mojoHandle];
180 if (idx == null) {
181 throw new Exception("Remove on a non-existent handle: idx = $idx.");
182 }
183 if (idx == 0) {
184 throw new Exception("The control handle (idx = 0) cannot be removed.");
185 }
186 // We don't use List.removeAt so that we know how to fix-up _handleIndices.
187 if (idx == _handleCount - 1) {
188 int handle = _handles[idx];
189 _handleIndices[handle] = null;
190 _handles.removeLast();
191 _signals.removeLast();
192 _ports.removeLast();
193 _handleCount--;
194 } else {
195 int last = _handleCount - 1;
196 _handles[idx] = _handles[last];
197 _signals[idx] = _signals[last];
198 _ports[idx] = _ports[last];
199 _handles.removeLast();
200 _signals.removeLast();
201 _ports.removeLast();
202 _handleIndices[_handles[idx]] = idx;
203 _handleCount--;
204 }
205 }
206
207 void _close(int mojoHandle) {
208 int idx = _handleIndices[mojoHandle];
209 if (idx == null) {
210 throw new Exception("Close on a non-existent handle: idx = $idx.");
211 }
212 if (idx == 0) {
213 throw new Exception("The control handle (idx = 0) cannot be closed.");
214 }
215 _tempHandle.h = _handles[idx];
216 _tempHandle.close();
217 _tempHandle.h = RawMojoHandle.INVALID;
218 _removeHandle(mojoHandle);
219 }
220
221 void _toggleWrite(int mojoHandle) {
222 int idx = _handleIndices[mojoHandle];
223 if (idx == null) {
224 throw new Exception("Toggle write on a non-existent handle: idx = $idx.");
225 }
226 if (idx == 0) {
227 throw new Exception("The control handle (idx = 0) cannot be toggled.");
228 }
229 _signals[idx] = MojoHandleSignals.toggleWrite(_signals[idx]);
230 }
231
232 void _pruneClosedHandles() {
233 List<int> closed = new List();
234 for (var h in _handles) {
235 _tempHandle.h = h;
236 MojoResult res = _tempHandle.wait(MojoHandleSignals.READWRITE, 0);
237 if ((!res.isOk) && (!res.isDeadlineExceeded)) {
238 closed.add(h);
239 }
240 _tempHandle.h = RawMojoHandle.INVALID;
241 }
242 for (var h in closed) {
243 _close(h);
244 }
245 }
246
247 static MojoResult _sendControlData(RawMojoHandle mojoHandle,
248 SendPort port,
249 int data) {
250 int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
251 if (controlHandle == RawMojoHandle.INVALID) {
252 throw new Exception("Found invalid control handle");
253 }
254 var result = _MojoHandleWatcherNatives.sendControlData(
255 controlHandle, mojoHandle.h, port, data);
256 return new MojoResult(result);
257 }
258
259 static Future<Isolate> Start() {
260 // 5. Return Future<bool> giving true on success.
261
262 // Make a control message pipe,
263 MojoMessagePipe pipe = new MojoMessagePipe();
264 int consumerHandle = pipe.endpoints[0].handle.h;
265 int producerHandle = pipe.endpoints[1].handle.h;
266
267 // Make a MojoHandleWatcher with one end.
268 MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
269
270 // Call setControlHandle with the other end.
271 _MojoHandleWatcherNatives.setControlHandle(producerHandle);
272
273 // Spawn the handle watcher isolate with the MojoHandleWatcher,
274 return Isolate.spawn(_handleWatcherIsolate, watcher);
275 }
276
277 static void Stop() {
278 _sendControlData(RawMojoHandle.INVALID, null, _encodeCommand(SHUTDOWN));
279 }
280
281 static MojoResult close(RawMojoHandle mojoHandle) {
282 return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE));
283 }
284
285 static MojoResult toggleWrite(RawMojoHandle mojoHandle) {
286 return _sendControlData(mojoHandle, null, _encodeCommand(TOGGLE_WRITE));
287 }
288
289 static MojoResult add(RawMojoHandle mojoHandle, SendPort port, int signals) {
290 return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals));
291 }
292
293 static MojoResult remove(RawMojoHandle mojoHandle) {
294 return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
295 }
296 }
OLDNEW
« no previous file with comments | « mojo/public/dart/src/handle.dart ('k') | mojo/public/dart/src/message_pipe.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698