Index: third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart |
diff --git a/third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart b/third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart |
deleted file mode 100644 |
index 4aeeaffd0bed4bb770a458fe63b0738240c5ae85..0000000000000000000000000000000000000000 |
--- a/third_party/mojo/src/mojo/public/dart/lib/src/handle_watcher.dart |
+++ /dev/null |
@@ -1,353 +0,0 @@ |
-// 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 internal; |
- |
-// The MojoHandleWatcher sends a stream of events to application isolates that |
-// register Mojo handles with it. Application isolates make the following calls: |
-// |
-// 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. |
-// |
-// 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 CLOSE = 2; |
- static const int TIMER = 3; |
- static const int SHUTDOWN = 4; |
- |
- static const int kMojoHandleInvalid = 0; |
- static const int kDeadlineIndefinite = -1; |
- |
- static const int kMojoResultOk = 0; |
- static const int kMojoResultDeadlineExceeded = 4; |
- static const int kMojoResultFailedPrecondition = 9; |
- |
- static const int kMojoSignalsReadable = (1 << 0); |
- static const int kMojoSignalsWritable = (1 << 1); |
- static const int kMojoSignalsPeerClosed = (1 << 2); |
- static const int kMojoSignalsAll = |
- kMojoSignalsReadable | kMojoSignalsWritable | kMojoSignalsPeerClosed; |
- |
- static int _encodeCommand(int cmd, [int signals = 0]) => |
- (cmd << 3) | (signals & kMojoSignalsAll); |
- static int _decodeCommand(int cmd) { |
- assert(kMojoSignalsAll < 1 << 3); |
- return cmd >> 3; |
- } |
- static int _decodeSignals(int cmd) { |
- return cmd & kMojoSignalsAll; |
- } |
- |
- // 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; |
- |
- // Priority queue of timers registered with the watcher. |
- TimerQueue _timerQueue; |
- |
- MojoHandleWatcher(this._controlHandle) |
- : _shutdown = false, |
- _handles = new List<int>(), |
- _ports = new List<SendPort>(), |
- _signals = new List<int>(), |
- _handleIndices = new Map<int, int>(), |
- _handleCount = 1, |
- _timerQueue = new TimerQueue() { |
- // Setup control handle. |
- _handles.add(_controlHandle); |
- _ports.add(null); // There is no port for the control handle. |
- _signals.add(kMojoSignalsReadable); |
- _handleIndices[_controlHandle] = 0; |
- } |
- |
- static void _handleWatcherIsolate(int consumerHandle) { |
- MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); |
- while (!watcher._shutdown) { |
- int deadline = watcher._processTimerDeadlines(); |
- // mwmr[0]: result, mwmr[1]: index, mwmr[2]: list of signal states. |
- List mwmr = MojoHandleNatives.waitMany( |
- watcher._handles, watcher._signals, deadline); |
- if ((mwmr[0] == kMojoResultOk) && (mwmr[1] == 0)) { |
- watcher._handleControlMessage(); |
- } else if ((mwmr[0] == kMojoResultOk) && (mwmr[1] > 0)) { |
- int handle = watcher._handles[mwmr[1]]; |
- |
- // Route event. |
- watcher._routeEvent(mwmr[2][mwmr[1]][0], mwmr[1]); |
- // Remove the handle from the list. |
- watcher._removeHandle(handle); |
- } else if (mwmr[0] != kMojoResultDeadlineExceeded) { |
- // Some handle was closed, but not by us. |
- // Find it and close it on our side. |
- watcher._pruneClosedHandles(mwmr[2]); |
- } |
- } |
- } |
- |
- void _routeEvent(int satisfiedSignals, int idx) { |
- _ports[idx].send([_signals[idx], satisfiedSignals & _signals[idx]]); |
- } |
- |
- void _handleControlMessage() { |
- List result = MojoHandleWatcherNatives.recvControlData(_controlHandle); |
- // result[0] = mojo handle if any, or a timer deadline in milliseconds. |
- // result[1] = SendPort if any. |
- // result[2] = command << 2 | WRITABLE | READABLE |
- |
- var signals = _decodeSignals(result[2]); |
- int command = _decodeCommand(result[2]); |
- switch (command) { |
- case ADD: |
- _addHandle(result[0], result[1], signals); |
- break; |
- case REMOVE: |
- _removeHandle(result[0]); |
- break; |
- case CLOSE: |
- _close(result[0], result[1]); |
- break; |
- case TIMER: |
- _timer(result[1], result[0]); |
- break; |
- case SHUTDOWN: |
- _shutdownHandleWatcher(result[1]); |
- break; |
- default: |
- throw "Invalid Command: $command"; |
- break; |
- } |
- } |
- |
- void _addHandle(int mojoHandle, SendPort port, int signals) { |
- int idx = _handleIndices[mojoHandle]; |
- if (idx == null) { |
- _handles.add(mojoHandle); |
- _ports.add(port); |
- _signals.add(signals); |
- _handleIndices[mojoHandle] = _handleCount; |
- _handleCount++; |
- } else { |
- assert(_ports[idx] == port); |
- assert(_handles[idx] == mojoHandle); |
- _signals[idx] |= signals; |
- } |
- } |
- |
- void _removeHandle(int mojoHandle) { |
- int idx = _handleIndices[mojoHandle]; |
- if (idx == null) { |
- throw "Remove on a non-existent handle: idx = $idx."; |
- } |
- if (idx == 0) { |
- throw "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; |
- _handleIndices[_handles[idx]] = null; |
- _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, SendPort port, {bool pruning: false}) { |
- assert(!pruning || (port == null)); |
- int idx = _handleIndices[mojoHandle]; |
- if (idx == null) { |
- // An app isolate may request that the handle watcher close a handle that |
- // has already been pruned. This happens when the app isolate has not yet |
- // received the PEER_CLOSED event. The app isolate will not close the |
- // handle, so we must do so here. |
- MojoHandleNatives.close(mojoHandle); |
- if (port != null) port.send(null); // Notify that close is done. |
- return; |
- } |
- if (idx == 0) { |
- throw "The control handle (idx = 0) cannot be closed."; |
- } |
- MojoHandleNatives.close(_handles[idx]); |
- if (port != null) port.send(null); // Notify that close is done. |
- if (pruning) { |
- // If this handle is being pruned, notify the application isolate |
- // by sending MojoHandleSignals.PEER_CLOSED. |
- _ports[idx].send([_signals[idx], kMojoSignalsPeerClosed]); |
- } |
- _removeHandle(mojoHandle); |
- } |
- |
- // Returns the next timer deadline in units of microseconds from 'now'. |
- int _processTimerDeadlines() { |
- int now = (new DateTime.now()).millisecondsSinceEpoch; |
- while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { |
- _timerQueue.currentPort.send(null); |
- _timerQueue.removeCurrent(); |
- now = (new DateTime.now()).millisecondsSinceEpoch; |
- } |
- return _timerQueue.hasTimer |
- ? (_timerQueue.currentTimeout - now) * 1000 |
- : kDeadlineIndefinite; |
- } |
- |
- void _timer(SendPort port, int deadline) { |
- _timerQueue.updateTimer(port, deadline); |
- } |
- |
- void _pruneClosedHandles(List<List<int>> states) { |
- List<int> closed = new List(); |
- for (var i = 0; i < _handles.length; i++) { |
- if (states != null) { |
- int signals = states[i][0]; |
- if ((signals & kMojoSignalsPeerClosed) != 0) { |
- closed.add(_handles[i]); |
- } |
- } else { |
- List mwr = MojoHandleNatives.wait(_handles[i], kMojoSignalsAll, 0); |
- if ((mwr[0] != kMojoResultOk) && |
- (mwr[0] != kMojoResultDeadlineExceeded)) { |
- closed.add(_handles[i]); |
- } |
- } |
- } |
- for (var h in closed) { |
- _close(h, null, pruning: true); |
- } |
- // '_close' updated the '_handles' array, so at this point the '_handles' |
- // array and the caller's 'states' array are mismatched. |
- } |
- |
- void _shutdownHandleWatcher(SendPort shutdownSendPort) { |
- _shutdown = true; |
- MojoHandleNatives.close(_controlHandle); |
- shutdownSendPort.send(null); |
- } |
- |
- static int _sendControlData(int rawHandle, SendPort port, int data) { |
- int controlHandle = MojoHandleWatcherNatives.getControlHandle(); |
- if (controlHandle == kMojoHandleInvalid) { |
- return kMojoResultFailedPrecondition; |
- } |
- |
- var result = MojoHandleWatcherNatives.sendControlData( |
- controlHandle, rawHandle, port, data); |
- return result; |
- } |
- |
- // Starts up the MojoHandleWatcher isolate. Should be called only once |
- // per VM process. |
- static Future<Isolate> _start() { |
- // Make a control message pipe, |
- List pipeEndpoints = MojoMessagePipeNatives.MojoCreateMessagePipe(0); |
- assert(pipeEndpoints != null); |
- assert((pipeEndpoints is List) && (pipeEndpoints.length == 3)); |
- assert(pipeEndpoints[0] == kMojoResultOk); |
- |
- int consumerHandle = pipeEndpoints[1]; |
- int producerHandle = pipeEndpoints[2]; |
- |
- // Call setControlHandle with the other end. |
- assert(producerHandle != kMojoHandleInvalid); |
- MojoHandleWatcherNatives.setControlHandle(producerHandle); |
- |
- // Spawn the handle watcher isolate with the MojoHandleWatcher, |
- return Isolate.spawn(_handleWatcherIsolate, consumerHandle); |
- } |
- |
- // Causes the MojoHandleWatcher isolate to exit. Should be called only |
- // once per VM process. |
- static void _stop() { |
- // Create a port for notification that the handle watcher has shutdown. |
- var shutdownReceivePort = new ReceivePort(); |
- var shutdownSendPort = shutdownReceivePort.sendPort; |
- |
- // Send the shutdown command. |
- _sendControlData( |
- kMojoHandleInvalid, shutdownSendPort, _encodeCommand(SHUTDOWN)); |
- |
- // Close the control handle. |
- int controlHandle = MojoHandleWatcherNatives.getControlHandle(); |
- MojoHandleNatives.close(controlHandle); |
- |
- // Invalidate the control handle. |
- MojoHandleWatcherNatives.setControlHandle(kMojoHandleInvalid); |
- |
- // Wait for the handle watcher isolate to exit. |
- shutdownReceivePort.first.then((_) { |
- shutdownReceivePort.close(); |
- }); |
- } |
- |
- // If wait is true, returns a future that resolves only after the handle |
- // has actually been closed by the handle watcher. Otherwise, returns a |
- // future that resolves immediately. |
- static Future<int> close(int mojoHandle, {bool wait: false}) { |
- //assert(MojoHandle._removeUnclosedHandle(mojoHandle)); |
- if (!wait) { |
- return new Future.value( |
- _sendControlData(mojoHandle, null, _encodeCommand(CLOSE))); |
- } |
- int result; |
- var completer = new Completer(); |
- var rawPort = new RawReceivePort((_) { |
- completer.complete(result); |
- }); |
- result = |
- _sendControlData(mojoHandle, rawPort.sendPort, _encodeCommand(CLOSE)); |
- return completer.future.then((r) { |
- rawPort.close(); |
- return r; |
- }); |
- } |
- |
- static int add(int mojoHandle, SendPort port, int signals) { |
- return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals)); |
- } |
- |
- static int remove(int mojoHandle) { |
- return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); |
- } |
- |
- static int timer(Object ignored, SendPort port, int deadline) { |
- // The deadline will be unwrapped before sending to the handle watcher. |
- return _sendControlData(deadline, port, _encodeCommand(TIMER)); |
- } |
-} |