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

Unified Diff: mojo/public/dart/src/handle_watcher.dart

Issue 800523004: Dart: Simplifies the handle watcher. Various cleanups and bugfixes. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: cleanup Created 5 years, 11 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 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/interface.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
index 459e705acb93fbbbf1cee561f99cbfb9e1663652..297f72d8fe6416725a89e812260f15400cff64da 100644
--- a/mojo/public/dart/src/handle_watcher.dart
+++ b/mojo/public/dart/src/handle_watcher.dart
@@ -33,23 +33,18 @@ class _MojoHandleWatcherNatives {
// 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 TIMER = 4;
- static const int SHUTDOWN = 5;
+ static const int CLOSE = 2;
+ static const int TIMER = 3;
+ static const int SHUTDOWN = 4;
static int _encodeCommand(int cmd, [int signals = 0]) =>
- (cmd << 2) | (signals & MojoHandleSignals.READWRITE);
+ (cmd << 2) | (signals & MojoHandleSignals.kReadWrite);
static int _decodeCommand(int cmd) => cmd >> 2;
// The Mojo handle over which control messages are sent.
@@ -73,8 +68,8 @@ class MojoHandleWatcher {
Map<int, int> _handleIndices;
// Since we are not storing wrapped handles, a dummy handle for when we need
- // a RawMojoHandle.
- RawMojoHandle _tempHandle;
+ // a MojoHandle.
+ MojoHandle _tempHandle;
// Priority queue of timers registered with the watcher.
TimerQueue _timerQueue;
@@ -86,12 +81,12 @@ class MojoHandleWatcher {
_signals = new List<int>(),
_handleIndices = new Map<int, int>(),
_handleCount = 1,
- _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID),
+ _tempHandle = new MojoHandle(MojoHandle.INVALID),
_timerQueue = new TimerQueue() {
// Setup control handle.
_handles.add(_controlHandle);
_ports.add(null); // There is no port for the control handle.
- _signals.add(MojoHandleSignals.READABLE);
+ _signals.add(MojoHandleSignals.kReadable);
_handleIndices[_controlHandle] = 0;
}
@@ -99,43 +94,38 @@ class MojoHandleWatcher {
MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle);
while (!watcher._shutdown) {
int deadline = watcher._processTimerDeadlines();
- MojoWaitManyResult res = RawMojoHandle.waitMany(watcher._handles,
- watcher._signals,
- deadline);
- if (res.result.isOk && res.index == 0) {
+ MojoWaitManyResult mwmr = MojoHandle.waitMany(
+ watcher._handles, watcher._signals, deadline);
+ if (mwmr.result.isOk && mwmr.index == 0) {
watcher._handleControlMessage();
- } else if (res.result.isOk && res.index > 0) {
- int handle = watcher._handles[res.index];
+ } else if (mwmr.result.isOk && (mwmr.index > 0)) {
+ int handle = watcher._handles[mwmr.index];
// Route event.
- watcher._routeEvent(res.index);
+ watcher._routeEvent(mwmr.index);
// Remove the handle from the list.
watcher._removeHandle(handle);
- } else if (res.areSignalStatesValid) {
+ } else if (!mwmr.result.isDeadlineExceeded) {
// Some handle was closed, but not by us.
// Find it and close it on our side.
- watcher._pruneClosedHandles(res.states);
+ watcher._pruneClosedHandles(mwmr.states);
}
}
}
void _routeEvent(int idx) {
int client_handle = _handles[idx];
- int signals = _signals[idx];
+ var signals = new MojoHandleSignals(_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;
+ bool readyWrite = signals.isWritable && _tempHandle.readyWrite;
+ bool readyRead = signals.isReadable && _tempHandle.readyRead;
+ _tempHandle.h = MojoHandle.INVALID;
+
+ var event = MojoHandleSignals.NONE;
+ event += readyRead ? MojoHandleSignals.READABLE : MojoHandleSignals.NONE;
+ event += readyWrite ? MojoHandleSignals.WRITABLE : MojoHandleSignals.NONE;
+ port.send([signals.value, event.value]);
}
void _handleControlMessage() {
@@ -144,7 +134,8 @@ class MojoHandleWatcher {
// result[1] = SendPort if any.
// result[2] = command << 2 | WRITABLE | READABLE
- int signals = result[2] & MojoHandleSignals.READWRITE;
+ var signals = new MojoHandleSignals(
+ result[2] & MojoHandleSignals.kReadWrite);
int command = _decodeCommand(result[2]);
switch (command) {
case ADD:
@@ -153,9 +144,6 @@ class MojoHandleWatcher {
case REMOVE:
_removeHandle(result[0]);
break;
- case TOGGLE_WRITE:
- _toggleWrite(result[0]);
- break;
case CLOSE:
_close(result[0]);
break;
@@ -163,29 +151,36 @@ class MojoHandleWatcher {
_timer(result[1], result[0]);
break;
case SHUTDOWN:
- _shutdownHandleWatcher();
+ _shutdownHandleWatcher(result[1]);
break;
default:
- throw new Exception("Invalid Command: $command");
+ throw "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 _addHandle(int mojoHandle, SendPort port, MojoHandleSignals signals) {
+ int idx = _handleIndices[mojoHandle];
+ if (idx == null) {
+ _handles.add(mojoHandle);
+ _ports.add(port);
+ _signals.add(signals.value);
+ _handleIndices[mojoHandle] = _handleCount;
+ _handleCount++;
+ } else {
+ assert(_ports[idx] == port);
+ assert(_handles[idx] == mojoHandle);
+ _signals[idx] |= signals.value;
+ }
}
void _removeHandle(int mojoHandle) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
- throw new Exception("Remove on a non-existent handle: idx = $idx.");
+ throw "Remove on a non-existent handle: idx = $idx.";
}
if (idx == 0) {
- throw new Exception("The control handle (idx = 0) cannot be removed.");
+ 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) {
@@ -197,6 +192,7 @@ class MojoHandleWatcher {
_handleCount--;
} else {
int last = _handleCount - 1;
+ _handleIndices[_handles[idx]] = null;
_handles[idx] = _handles[last];
_signals[idx] = _signals[last];
_ports[idx] = _ports[last];
@@ -211,18 +207,21 @@ class MojoHandleWatcher {
void _close(int mojoHandle, {bool pruning : false}) {
int idx = _handleIndices[mojoHandle];
if (idx == null) {
- throw new Exception("Close on a non-existent handle: idx = $idx.");
+ // A client may request to close a handle that has already been closed on
+ // the other side and pruned, but before receiving notification from the
+ // handle watcher.
+ return;
}
if (idx == 0) {
- throw new Exception("The control handle (idx = 0) cannot be closed.");
+ throw "The control handle (idx = 0) cannot be closed.";
}
_tempHandle.h = _handles[idx];
_tempHandle.close();
- _tempHandle.h = RawMojoHandle.INVALID;
+ _tempHandle.h = MojoHandle.INVALID;
if (pruning) {
// If this handle is being pruned, notify the application isolate
- // by sending MojoHandleSignals.NONE.
- _ports[idx].send(MojoHandleSignals.NONE);
+ // by sending MojoHandleSignals.PEER_CLOSED.
+ _ports[idx].send([_signals[idx], MojoHandleSignals.kPeerClosed]);
}
_removeHandle(mojoHandle);
}
@@ -236,55 +235,54 @@ class MojoHandleWatcher {
now = (new DateTime.now()).millisecondsSinceEpoch;
}
return _timerQueue.hasTimer ? (_timerQueue.currentTimeout - now) * 1000
- : RawMojoHandle.DEADLINE_INDEFINITE;
+ : MojoHandle.DEADLINE_INDEFINITE;
}
void _timer(SendPort port, int deadline) {
_timerQueue.updateTimer(port, deadline);
}
- void _toggleWrite(int mojoHandle) {
- int idx = _handleIndices[mojoHandle];
- if (idx == null) {
- throw new Exception(
- "Toggle write on a non-existent handle: $mojoHandle.");
- }
- if (idx == 0) {
- throw new Exception("The control handle (idx = 0) cannot be toggled.");
- }
- _signals[idx] = MojoHandleSignals.toggleWrite(_signals[idx]);
- }
-
void _pruneClosedHandles(List<MojoHandleSignalsState> states) {
List<int> closed = new List();
- for (var i=0; i<_handles.length; i++) {
- if (MojoHandleSignals.isPeerClosed(states[i].satisfied_signals)) {
- closed.add(_handles[i]);
+ for (var i = 0; i < _handles.length; i++) {
+ if (states != null) {
+ var signals = new MojoHandleSignals(states[i].satisfied_signals);
+ if (signals.isPeerClosed) {
+ closed.add(_handles[i]);
+ }
+ } else {
+ _tempHandle.h = h;
+ MojoResult res = _tempHandle.wait(MojoHandleSignals.kReadWrite, 0);
+ if ((!res.isOk) && (!res.isDeadlineExceeded)) {
+ closed.add(h);
+ }
+ _tempHandle.h = MojoHandle.INVALID;
}
}
for (var h in closed) {
- _close(h, pruning: true);
+ _close(h, pruning: true);
}
// '_close' updated the '_handles' array, so at this point the '_handles'
// array and the caller's 'states' array are mismatched.
}
- void _shutdownHandleWatcher() {
+ void _shutdownHandleWatcher(SendPort shutdownSendPort) {
_shutdown = true;
_tempHandle.h = _controlHandle;
_tempHandle.close();
- _tempHandle.h = RawMojoHandle.INVALID;
+ _tempHandle.h = MojoHandle.INVALID;
+ shutdownSendPort.send(null);
}
- static MojoResult _sendControlData(RawMojoHandle mojoHandle,
+ static MojoResult _sendControlData(MojoHandle mojoHandle,
SendPort port,
int data) {
int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
- if (controlHandle == RawMojoHandle.INVALID) {
- throw new Exception("Found invalid control handle");
+ if (controlHandle == MojoHandle.INVALID) {
+ return MojoResult.FAILED_PRECONDITION;
}
- int rawHandle = RawMojoHandle.INVALID;
+ int rawHandle = MojoHandle.INVALID;
if (mojoHandle != null) {
rawHandle = mojoHandle.h;
}
@@ -300,6 +298,7 @@ class MojoHandleWatcher {
int producerHandle = pipe.endpoints[1].handle.h;
// Call setControlHandle with the other end.
+ assert(producerHandle != MojoHandle.INVALID);
_MojoHandleWatcherNatives.setControlHandle(producerHandle);
// Spawn the handle watcher isolate with the MojoHandleWatcher,
@@ -307,37 +306,42 @@ class MojoHandleWatcher {
}
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(null, null, _encodeCommand(SHUTDOWN));
+ _sendControlData(null, shutdownSendPort, _encodeCommand(SHUTDOWN));
// Close the control handle.
int controlHandle = _MojoHandleWatcherNatives.getControlHandle();
- var handle = new RawMojoHandle(controlHandle);
+ var handle = new MojoHandle(controlHandle);
handle.close();
// Invalidate the control handle.
- _MojoHandleWatcherNatives.setControlHandle(RawMojoHandle.INVALID);
- }
+ _MojoHandleWatcherNatives.setControlHandle(MojoHandle.INVALID);
- static MojoResult close(RawMojoHandle mojoHandle) {
- return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE));
+ // Wait for the handle watcher isolate to exit.
+ shutdownReceivePort.first.then((_) {
+ shutdownReceivePort.close();
+ });
}
- static MojoResult toggleWrite(RawMojoHandle mojoHandle) {
- return _sendControlData(mojoHandle, null, _encodeCommand(TOGGLE_WRITE));
+ static MojoResult close(MojoHandle mojoHandle) {
+ return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE));
}
- static MojoResult add(RawMojoHandle mojoHandle, SendPort port, int signals) {
+ static MojoResult add(MojoHandle mojoHandle, SendPort port, int signals) {
return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals));
}
- static MojoResult remove(RawMojoHandle mojoHandle) {
+ static MojoResult remove(MojoHandle mojoHandle) {
return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE));
}
static MojoResult timer(SendPort port, int deadline) {
// The deadline will be unwrapped before sending to the handle watcher.
return _sendControlData(
- new RawMojoHandle(deadline), port, _encodeCommand(TIMER));
+ new MojoHandle(deadline), port, _encodeCommand(TIMER));
}
}
« no previous file with comments | « mojo/public/dart/src/handle.dart ('k') | mojo/public/dart/src/interface.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698