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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/public/dart/src/handle_watcher.dart
diff --git a/mojo/public/dart/src/handle_watcher.dart b/mojo/public/dart/src/handle_watcher.dart
new file mode 100644
index 0000000000000000000000000000000000000000..47f36756bba1777b742d92980de5f9834b86eb3b
--- /dev/null
+++ b/mojo/public/dart/src/handle_watcher.dart
@@ -0,0 +1,296 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+part of core;
+
+class _MojoHandleWatcherNatives {
+ static int sendControlData(
+ int controlHandle, int mojoHandle, SendPort port, int data)
+ native "MojoHandleWatcher_SendControlData";
+ static List recvControlData(int controlHandle)
+ native "MojoHandleWatcher_RecvControlData";
+ static int setControlHandle(int controlHandle)
+ native "MojoHandleWatcher_SetControlHandle";
+ static int getControlHandle()
+ native "MojoHandleWatcher_GetControlHandle";
+}
+
+// The MojoHandleWatcher sends a stream of events to application isolates that
+// register Mojo handles with it. Application isolates make the following calls:
+//
+// Start() - Starts up the MojoHandleWatcher isolate. Should be called only once
+// per VM process.
+//
+// Stop() - Causes the MojoHandleWatcher isolate to exit.
+//
+// add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add
+// 'handle' to the set of handles it watches, and to notify the calling
+// isolate only for the events specified by 'signals' using the send port
+// 'port'
+//
+// remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle'
+// from the set of handles it watches. This allows the application isolate
+// to, e.g., pause the stream of events.
+//
+// toggleWrite(handle) - Modifies the set of signals that an application isolate
+// wishes to be notified about. Whether the application isolate should be
+// be notified about a handle ready for writing is made the opposite.
+//
+// close(handle) - Notifies the HandleWatcherIsolate that a handle it is
+// watching should be removed from its set and closed.
+class MojoHandleWatcher {
+ // Control commands.
+ static const int ADD = 0;
+ static const int REMOVE = 1;
+ static const int TOGGLE_WRITE = 2;
+ static const int CLOSE = 3;
+ static const int SHUTDOWN = 4;
+
+ static int _encodeCommand(int cmd, [int signals = 0]) =>
+ (cmd << 2) | (signals & MojoHandleSignals.READWRITE);
+ static int _decodeCommand(int cmd) => cmd >> 2;
+
+ // The Mojo handle over which control messages are sent.
+ int _controlHandle;
+
+ // Whether the handle watcher should shut down.
+ bool _shutdown;
+
+ // The list of handles being watched.
+ List<int> _handles;
+ int _handleCount;
+
+ // A port for each handle on which to send events back to the isolate that
+ // owns the handle.
+ List<SendPort> _ports;
+
+ // The signals that we care about for each handle.
+ List<int> _signals;
+
+ // A mapping from Mojo handles to their indices in _handles.
+ Map<int, int> _handleIndices;
+
+ // Since we are not storing wrapped handles, a dummy handle for when we need
+ // a RawMojoHandle.
+ RawMojoHandle _tempHandle;
+
+ MojoHandleWatcher(this._controlHandle) :
+ _shutdown = false,
+ _handles = new List<int>(),
+ _ports = new List<SendPort>(),
+ _signals = new List<int>(),
+ _handleIndices = new Map<int, int>(),
+ _handleCount = 1,
+ _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID) {
+ // Setup control handle.
+ _handles.add(_controlHandle);
+ _ports.add(null); // There is no port for the control handle.
+ _signals.add(MojoHandleSignals.READABLE);
+ _handleIndices[_controlHandle] = 0;
+ }
+
+ static void _handleWatcherIsolate(MojoHandleWatcher watcher) {
+ while (!watcher._shutdown) {
+ int res = RawMojoHandle.waitMany(watcher._handles,
+ watcher._signals,
+ RawMojoHandle.DEADLINE_INDEFINITE);
+ if (res == 0) {
+ watcher._handleControlMessage();
+ } else if (res > 0) {
+ int handle = watcher._handles[res];
+ // Route event.
+ watcher._routeEvent(res);
+ // Remove the handle from the list.
+ watcher._removeHandle(handle);
+ } else if (res == MojoResult.kFailedPrecondition) {
+ // None of the handles can ever be satisfied, including the control
+ // handle. This probably means we are going down. Clean up and
+ // shutdown.
+ watcher._pruneClosedHandles();
+ watcher._shutdown = true;
+ } else {
+ // Some handle was closed, but not by us.
+ // We have to go through the list and find it.
+ watcher._pruneClosedHandles();
+ }
+ }
+ }
+
+ void _routeEvent(int idx) {
+ int client_handle = _handles[idx];
+ int signals = _signals[idx];
+ SendPort port = _ports[idx];
+
+ _tempHandle.h = client_handle;
+ bool readyWrite =
+ MojoHandleSignals.isWritable(signals) && _tempHandle.readyWrite();
+ bool readyRead =
+ MojoHandleSignals.isReadable(signals) && _tempHandle.readyRead();
+ if (readyRead && readyWrite) {
+ port.send(MojoHandleSignals.READWRITE);
+ } else if (readyWrite) {
+ port.send(MojoHandleSignals.WRITABLE);
+ } else if (readyRead) {
+ port.send(MojoHandleSignals.READABLE);
+ }
+ _tempHandle.h = RawMojoHandle.INVALID;
+ }
+
+ void _handleControlMessage() {
+ List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle);
+ // result[0] = mojo handle if any
+ // result[1] = SendPort if any
+ // result[2] = command << 2 | WRITABLE | READABLE
+
+ int signals = result[2] & MojoHandleSignals.READWRITE;
+ int command = _decodeCommand(result[2]);
+ switch (command) {
+ case ADD:
+ _addHandle(result[0], result[1], signals);
+ break;
+ case REMOVE:
+ _removeHandle(result[0]);
+ break;
+ case TOGGLE_WRITE:
+ _toggleWrite(result[0]);
+ break;
+ case CLOSE:
+ _close(result[0]);
+ break;
+ case SHUTDOWN:
+ _shutdown = true;
+ break;
+ default:
+ throw new Exception("Invalid Command: $command");
+ break;
+ }
+ }
+
+ void _addHandle(int mojoHandle, SendPort port, int signals) {
+ _handles.add(mojoHandle);
+ _ports.add(port);
+ _signals.add(signals & MojoHandleSignals.READWRITE);
+ _handleIndices[mojoHandle] = _handleCount;
+ _handleCount++;
+ }
+
+ void _removeHandle(int mojoHandle) {
+ int idx = _handleIndices[mojoHandle];
+ if (idx == null) {
+ throw new Exception("Remove on a non-existent handle: idx = $idx.");
+ }
+ if (idx == 0) {
+ throw new Exception("The control handle (idx = 0) cannot be removed.");
+ }
+ // We don't use List.removeAt so that we know how to fix-up _handleIndices.
+ if (idx == _handleCount - 1) {
+ int handle = _handles[idx];
+ _handleIndices[handle] = null;
+ _handles.removeLast();
+ _signals.removeLast();
+ _ports.removeLast();
+ _handleCount--;
+ } else {
+ int last = _handleCount - 1;
+ _handles[idx] = _handles[last];
+ _signals[idx] = _signals[last];
+ _ports[idx] = _ports[last];
+ _handles.removeLast();
+ _signals.removeLast();
+ _ports.removeLast();
+ _handleIndices[_handles[idx]] = idx;
+ _handleCount--;
+ }
+ }
+
+ void _close(int mojoHandle) {
+ int idx = _handleIndices[mojoHandle];
+ if (idx == null) {
+ throw new Exception("Close on a non-existent handle: idx = $idx.");
+ }
+ if (idx == 0) {
+ throw new Exception("The control handle (idx = 0) cannot be closed.");
+ }
+ _tempHandle.h = _handles[idx];
+ _tempHandle.close();
+ _tempHandle.h = RawMojoHandle.INVALID;
+ _removeHandle(mojoHandle);
+ }
+
+ void _toggleWrite(int mojoHandle) {
+ int idx = _handleIndices[mojoHandle];
+ if (idx == null) {
+ throw new Exception("Toggle write on a non-existent handle: idx = $idx.");
+ }
+ if (idx == 0) {
+ throw new Exception("The control handle (idx = 0) cannot be toggled.");
+ }
+ _signals[idx] = MojoHandleSignals.toggleWrite(_signals[idx]);
+ }
+
+ void _pruneClosedHandles() {
+ List<int> closed = new List();
+ for (var h in _handles) {
+ _tempHandle.h = h;
+ MojoResult res = _tempHandle.wait(MojoHandleSignals.READWRITE, 0);
+ if ((!res.isOk) && (!res.isDeadlineExceeded)) {
+ closed.add(h);
+ }
+ _tempHandle.h = RawMojoHandle.INVALID;
+ }
+ for (var h in closed) {
+ _close(h);
+ }
+ }
+
+ static MojoResult _sendControlData(RawMojoHandle mojoHandle,
+ SendPort port,
+ int data) {
+ int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
+ if (controlHandle == RawMojoHandle.INVALID) {
+ throw new Exception("Found invalid control handle");
+ }
+ var result = _MojoHandleWatcherNatives.sendControlData(
+ controlHandle, mojoHandle.h, port, data);
+ return new MojoResult(result);
+ }
+
+ static Future<Isolate> Start() {
+ // 5. Return Future<bool> giving true on success.
+
+ // Make a control message pipe,
+ MojoMessagePipe pipe = new MojoMessagePipe();
+ int consumerHandle = pipe.endpoints[0].handle.h;
+ int producerHandle = pipe.endpoints[1].handle.h;
+
+ // Make a MojoHandleWatcher with one end.
+ MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
+
+ // Call setControlHandle with the other end.
+ _MojoHandleWatcherNatives.setControlHandle(producerHandle);
+
+ // Spawn the handle watcher isolate with the MojoHandleWatcher,
+ return Isolate.spawn(_handleWatcherIsolate, watcher);
+ }
+
+ static void Stop() {
+ _sendControlData(RawMojoHandle.INVALID, null, _encodeCommand(SHUTDOWN));
+ }
+
+ static MojoResult close(RawMojoHandle mojoHandle) {
+ return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE));
+ }
+
+ static MojoResult toggleWrite(RawMojoHandle mojoHandle) {
+ return _sendControlData(mojoHandle, null, _encodeCommand(TOGGLE_WRITE));
+ }
+
+ static MojoResult add(RawMojoHandle mojoHandle, SendPort port, int signals) {
+ return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals));
+ }
+
+ static MojoResult remove(RawMojoHandle mojoHandle) {
+ return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
+ }
+}
« 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