| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 part of core; | 5 part of internal; |
| 6 | |
| 7 class _MojoHandleWatcherNatives { | |
| 8 static int sendControlData(int controlHandle, int mojoHandle, SendPort port, | |
| 9 int data) native "MojoHandleWatcher_SendControlData"; | |
| 10 static List recvControlData( | |
| 11 int controlHandle) native "MojoHandleWatcher_RecvControlData"; | |
| 12 static int setControlHandle( | |
| 13 int controlHandle) native "MojoHandleWatcher_SetControlHandle"; | |
| 14 static int getControlHandle() native "MojoHandleWatcher_GetControlHandle"; | |
| 15 } | |
| 16 | 6 |
| 17 // The MojoHandleWatcher sends a stream of events to application isolates that | 7 // The MojoHandleWatcher sends a stream of events to application isolates that |
| 18 // register Mojo handles with it. Application isolates make the following calls: | 8 // register Mojo handles with it. Application isolates make the following calls: |
| 19 // | 9 // |
| 20 // add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add | 10 // add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add |
| 21 // 'handle' to the set of handles it watches, and to notify the calling | 11 // 'handle' to the set of handles it watches, and to notify the calling |
| 22 // isolate only for the events specified by 'signals' using the send port | 12 // isolate only for the events specified by 'signals' using the send port |
| 23 // 'port' | 13 // 'port' |
| 24 // | 14 // |
| 25 // remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle' | 15 // remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle' |
| 26 // from the set of handles it watches. This allows the application isolate | 16 // from the set of handles it watches. This allows the application isolate |
| 27 // to, e.g., pause the stream of events. | 17 // to, e.g., pause the stream of events. |
| 28 // | 18 // |
| 29 // close(handle) - Notifies the HandleWatcherIsolate that a handle it is | 19 // close(handle) - Notifies the HandleWatcherIsolate that a handle it is |
| 30 // watching should be removed from its set and closed. | 20 // watching should be removed from its set and closed. |
| 31 class MojoHandleWatcher { | 21 class MojoHandleWatcher { |
| 32 // Control commands. | 22 // Control commands. |
| 33 static const int ADD = 0; | 23 static const int ADD = 0; |
| 34 static const int REMOVE = 1; | 24 static const int REMOVE = 1; |
| 35 static const int CLOSE = 2; | 25 static const int CLOSE = 2; |
| 36 static const int TIMER = 3; | 26 static const int TIMER = 3; |
| 37 static const int SHUTDOWN = 4; | 27 static const int SHUTDOWN = 4; |
| 38 | 28 |
| 29 static const int kMojoHandleInvalid = 0; |
| 30 static const int kDeadlineIndefinite = -1; |
| 31 |
| 32 static const int kMojoResultOk = 0; |
| 33 static const int kMojoResultDeadlineExceeded = -4; |
| 34 static const int kMojoResultFailedPrecondition = -9; |
| 35 |
| 36 static const int kMojoSignalsReadable = (1 << 0); |
| 37 static const int kMojoSignalsWritable = (1 << 1); |
| 38 static const int kMojoSignalsPeerClosed = (1 << 2); |
| 39 static const int kMojoSignalsAll = |
| 40 kMojoSignalsReadable | kMojoSignalsWritable | kMojoSignalsPeerClosed; |
| 41 |
| 39 static int _encodeCommand(int cmd, [int signals = 0]) => | 42 static int _encodeCommand(int cmd, [int signals = 0]) => |
| 40 (cmd << 3) | (signals & MojoHandleSignals.kAll); | 43 (cmd << 3) | (signals & kMojoSignalsAll); |
| 41 static int _decodeCommand(int cmd) { | 44 static int _decodeCommand(int cmd) { |
| 42 assert(MojoHandleSignals.kAll < 1 << 3); | 45 assert(kMojoSignalsAll < 1 << 3); |
| 43 return cmd >> 3; | 46 return cmd >> 3; |
| 44 } | 47 } |
| 45 static MojoHandleSignals _decodeSignals(int cmd) { | 48 static int _decodeSignals(int cmd) { |
| 46 return new MojoHandleSignals(cmd & MojoHandleSignals.kAll); | 49 return cmd & kMojoSignalsAll; |
| 47 } | 50 } |
| 48 | 51 |
| 49 // The Mojo handle over which control messages are sent. | 52 // The Mojo handle over which control messages are sent. |
| 50 int _controlHandle; | 53 int _controlHandle; |
| 51 | 54 |
| 52 // Whether the handle watcher should shut down. | 55 // Whether the handle watcher should shut down. |
| 53 bool _shutdown; | 56 bool _shutdown; |
| 54 | 57 |
| 55 // The list of handles being watched. | 58 // The list of handles being watched. |
| 56 List<int> _handles; | 59 List<int> _handles; |
| 57 int _handleCount; | 60 int _handleCount; |
| 58 | 61 |
| 59 // A port for each handle on which to send events back to the isolate that | 62 // A port for each handle on which to send events back to the isolate that |
| 60 // owns the handle. | 63 // owns the handle. |
| 61 List<SendPort> _ports; | 64 List<SendPort> _ports; |
| 62 | 65 |
| 63 // The signals that we care about for each handle. | 66 // The signals that we care about for each handle. |
| 64 List<int> _signals; | 67 List<int> _signals; |
| 65 | 68 |
| 66 // A mapping from Mojo handles to their indices in _handles. | 69 // A mapping from Mojo handles to their indices in _handles. |
| 67 Map<int, int> _handleIndices; | 70 Map<int, int> _handleIndices; |
| 68 | 71 |
| 69 // Since we are not storing wrapped handles, a dummy handle for when we need | |
| 70 // a MojoHandle. | |
| 71 MojoHandle _tempHandle; | |
| 72 | |
| 73 // Priority queue of timers registered with the watcher. | 72 // Priority queue of timers registered with the watcher. |
| 74 TimerQueue _timerQueue; | 73 TimerQueue _timerQueue; |
| 75 | 74 |
| 76 MojoHandleWatcher(this._controlHandle) | 75 MojoHandleWatcher(this._controlHandle) |
| 77 : _shutdown = false, | 76 : _shutdown = false, |
| 78 _handles = new List<int>(), | 77 _handles = new List<int>(), |
| 79 _ports = new List<SendPort>(), | 78 _ports = new List<SendPort>(), |
| 80 _signals = new List<int>(), | 79 _signals = new List<int>(), |
| 81 _handleIndices = new Map<int, int>(), | 80 _handleIndices = new Map<int, int>(), |
| 82 _handleCount = 1, | 81 _handleCount = 1, |
| 83 _tempHandle = new MojoHandle(MojoHandle.INVALID), | |
| 84 _timerQueue = new TimerQueue() { | 82 _timerQueue = new TimerQueue() { |
| 85 // Setup control handle. | 83 // Setup control handle. |
| 86 _handles.add(_controlHandle); | 84 _handles.add(_controlHandle); |
| 87 _ports.add(null); // There is no port for the control handle. | 85 _ports.add(null); // There is no port for the control handle. |
| 88 _signals.add(MojoHandleSignals.kReadable); | 86 _signals.add(kMojoSignalsReadable); |
| 89 _handleIndices[_controlHandle] = 0; | 87 _handleIndices[_controlHandle] = 0; |
| 90 } | 88 } |
| 91 | 89 |
| 92 static void _handleWatcherIsolate(int consumerHandle) { | 90 static void _handleWatcherIsolate(int consumerHandle) { |
| 93 MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); | 91 MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); |
| 94 while (!watcher._shutdown) { | 92 while (!watcher._shutdown) { |
| 95 int deadline = watcher._processTimerDeadlines(); | 93 int deadline = watcher._processTimerDeadlines(); |
| 96 MojoWaitManyResult mwmr = | 94 // mwmr[0]: result, mwmr[1]: index, mwmr[2]: list of signal states. |
| 97 MojoHandle.waitMany(watcher._handles, watcher._signals, deadline); | 95 List mwmr = MojoHandleNatives.waitMany( |
| 98 if (mwmr.result.isOk && mwmr.index == 0) { | 96 watcher._handles, watcher._signals, deadline); |
| 97 if ((mwmr[0] == kMojoResultOk) && (mwmr[1] == 0)) { |
| 99 watcher._handleControlMessage(); | 98 watcher._handleControlMessage(); |
| 100 } else if (mwmr.result.isOk && (mwmr.index > 0)) { | 99 } else if ((mwmr[0] == kMojoResultOk) && (mwmr[1] > 0)) { |
| 101 int handle = watcher._handles[mwmr.index]; | 100 int handle = watcher._handles[mwmr[1]]; |
| 102 | 101 |
| 103 // Route event. | 102 // Route event. |
| 104 watcher._routeEvent( | 103 watcher._routeEvent( |
| 105 mwmr.states[mwmr.index].satisfied_signals, mwmr.index); | 104 mwmr[2][mwmr[1]][0], mwmr[1]); |
| 106 // Remove the handle from the list. | 105 // Remove the handle from the list. |
| 107 watcher._removeHandle(handle); | 106 watcher._removeHandle(handle); |
| 108 } else if (!mwmr.result.isDeadlineExceeded) { | 107 } else if (mwmr[0] != kMojoResultDeadlineExceeded) { |
| 109 // Some handle was closed, but not by us. | 108 // Some handle was closed, but not by us. |
| 110 // Find it and close it on our side. | 109 // Find it and close it on our side. |
| 111 watcher._pruneClosedHandles(mwmr.states); | 110 watcher._pruneClosedHandles(mwmr[2]); |
| 112 } | 111 } |
| 113 } | 112 } |
| 114 } | 113 } |
| 115 | 114 |
| 116 void _routeEvent(int satisfiedSignals, int idx) { | 115 void _routeEvent(int satisfiedSignals, int idx) { |
| 117 _ports[idx].send([_signals[idx], satisfiedSignals & _signals[idx]]); | 116 _ports[idx].send([_signals[idx], satisfiedSignals & _signals[idx]]); |
| 118 } | 117 } |
| 119 | 118 |
| 120 void _handleControlMessage() { | 119 void _handleControlMessage() { |
| 121 List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle); | 120 List result = MojoHandleWatcherNatives.recvControlData(_controlHandle); |
| 122 // result[0] = mojo handle if any, or a timer deadline in milliseconds. | 121 // result[0] = mojo handle if any, or a timer deadline in milliseconds. |
| 123 // result[1] = SendPort if any. | 122 // result[1] = SendPort if any. |
| 124 // result[2] = command << 2 | WRITABLE | READABLE | 123 // result[2] = command << 2 | WRITABLE | READABLE |
| 125 | 124 |
| 126 var signals = _decodeSignals(result[2]); | 125 var signals = _decodeSignals(result[2]); |
| 127 int command = _decodeCommand(result[2]); | 126 int command = _decodeCommand(result[2]); |
| 128 switch (command) { | 127 switch (command) { |
| 129 case ADD: | 128 case ADD: |
| 130 _addHandle(result[0], result[1], signals); | 129 _addHandle(result[0], result[1], signals); |
| 131 break; | 130 break; |
| 132 case REMOVE: | 131 case REMOVE: |
| 133 _removeHandle(result[0]); | 132 _removeHandle(result[0]); |
| 134 break; | 133 break; |
| 135 case CLOSE: | 134 case CLOSE: |
| 136 _close(result[0], result[1]); | 135 _close(result[0], result[1]); |
| 137 break; | 136 break; |
| 138 case TIMER: | 137 case TIMER: |
| 139 _timer(result[1], result[0]); | 138 _timer(result[1], result[0]); |
| 140 break; | 139 break; |
| 141 case SHUTDOWN: | 140 case SHUTDOWN: |
| 142 _shutdownHandleWatcher(result[1]); | 141 _shutdownHandleWatcher(result[1]); |
| 143 break; | 142 break; |
| 144 default: | 143 default: |
| 145 throw "Invalid Command: $command"; | 144 throw "Invalid Command: $command"; |
| 146 break; | 145 break; |
| 147 } | 146 } |
| 148 } | 147 } |
| 149 | 148 |
| 150 void _addHandle(int mojoHandle, SendPort port, MojoHandleSignals signals) { | 149 void _addHandle(int mojoHandle, SendPort port, int signals) { |
| 151 int idx = _handleIndices[mojoHandle]; | 150 int idx = _handleIndices[mojoHandle]; |
| 152 if (idx == null) { | 151 if (idx == null) { |
| 153 _handles.add(mojoHandle); | 152 _handles.add(mojoHandle); |
| 154 _ports.add(port); | 153 _ports.add(port); |
| 155 _signals.add(signals.value); | 154 _signals.add(signals); |
| 156 _handleIndices[mojoHandle] = _handleCount; | 155 _handleIndices[mojoHandle] = _handleCount; |
| 157 _handleCount++; | 156 _handleCount++; |
| 158 } else { | 157 } else { |
| 159 assert(_ports[idx] == port); | 158 assert(_ports[idx] == port); |
| 160 assert(_handles[idx] == mojoHandle); | 159 assert(_handles[idx] == mojoHandle); |
| 161 _signals[idx] |= signals.value; | 160 _signals[idx] |= signals; |
| 162 } | 161 } |
| 163 } | 162 } |
| 164 | 163 |
| 165 void _removeHandle(int mojoHandle) { | 164 void _removeHandle(int mojoHandle) { |
| 166 int idx = _handleIndices[mojoHandle]; | 165 int idx = _handleIndices[mojoHandle]; |
| 167 if (idx == null) { | 166 if (idx == null) { |
| 168 throw "Remove on a non-existent handle: idx = $idx."; | 167 throw "Remove on a non-existent handle: idx = $idx."; |
| 169 } | 168 } |
| 170 if (idx == 0) { | 169 if (idx == 0) { |
| 171 throw "The control handle (idx = 0) cannot be removed."; | 170 throw "The control handle (idx = 0) cannot be removed."; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 193 } | 192 } |
| 194 | 193 |
| 195 void _close(int mojoHandle, SendPort port, {bool pruning: false}) { | 194 void _close(int mojoHandle, SendPort port, {bool pruning: false}) { |
| 196 assert(!pruning || (port == null)); | 195 assert(!pruning || (port == null)); |
| 197 int idx = _handleIndices[mojoHandle]; | 196 int idx = _handleIndices[mojoHandle]; |
| 198 if (idx == null) { | 197 if (idx == null) { |
| 199 // An app isolate may request that the handle watcher close a handle that | 198 // An app isolate may request that the handle watcher close a handle that |
| 200 // has already been pruned. This happens when the app isolate has not yet | 199 // has already been pruned. This happens when the app isolate has not yet |
| 201 // received the PEER_CLOSED event. The app isolate will not close the | 200 // received the PEER_CLOSED event. The app isolate will not close the |
| 202 // handle, so we must do so here. | 201 // handle, so we must do so here. |
| 203 _tempHandle._set(mojoHandle); | 202 MojoHandleNatives.close(mojoHandle); |
| 204 _tempHandle.close(); | |
| 205 if (port != null) port.send(null); // Notify that close is done. | 203 if (port != null) port.send(null); // Notify that close is done. |
| 206 return; | 204 return; |
| 207 } | 205 } |
| 208 if (idx == 0) { | 206 if (idx == 0) { |
| 209 throw "The control handle (idx = 0) cannot be closed."; | 207 throw "The control handle (idx = 0) cannot be closed."; |
| 210 } | 208 } |
| 211 _tempHandle._set(_handles[idx]); | 209 MojoHandleNatives.close(_handles[idx]); |
| 212 _tempHandle.close(); | |
| 213 if (port != null) port.send(null); // Notify that close is done. | 210 if (port != null) port.send(null); // Notify that close is done. |
| 214 if (pruning) { | 211 if (pruning) { |
| 215 // If this handle is being pruned, notify the application isolate | 212 // If this handle is being pruned, notify the application isolate |
| 216 // by sending MojoHandleSignals.PEER_CLOSED. | 213 // by sending MojoHandleSignals.PEER_CLOSED. |
| 217 _ports[idx].send([_signals[idx], MojoHandleSignals.kPeerClosed]); | 214 _ports[idx].send([_signals[idx], kMojoSignalsPeerClosed]); |
| 218 } | 215 } |
| 219 _removeHandle(mojoHandle); | 216 _removeHandle(mojoHandle); |
| 220 } | 217 } |
| 221 | 218 |
| 222 // Returns the next timer deadline in units of microseconds from 'now'. | 219 // Returns the next timer deadline in units of microseconds from 'now'. |
| 223 int _processTimerDeadlines() { | 220 int _processTimerDeadlines() { |
| 224 int now = (new DateTime.now()).millisecondsSinceEpoch; | 221 int now = (new DateTime.now()).millisecondsSinceEpoch; |
| 225 while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { | 222 while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { |
| 226 _timerQueue.currentPort.send(null); | 223 _timerQueue.currentPort.send(null); |
| 227 _timerQueue.removeCurrent(); | 224 _timerQueue.removeCurrent(); |
| 228 now = (new DateTime.now()).millisecondsSinceEpoch; | 225 now = (new DateTime.now()).millisecondsSinceEpoch; |
| 229 } | 226 } |
| 230 return _timerQueue.hasTimer | 227 return _timerQueue.hasTimer |
| 231 ? (_timerQueue.currentTimeout - now) * 1000 | 228 ? (_timerQueue.currentTimeout - now) * 1000 |
| 232 : MojoHandle.DEADLINE_INDEFINITE; | 229 : kDeadlineIndefinite; |
| 233 } | 230 } |
| 234 | 231 |
| 235 void _timer(SendPort port, int deadline) { | 232 void _timer(SendPort port, int deadline) { |
| 236 _timerQueue.updateTimer(port, deadline); | 233 _timerQueue.updateTimer(port, deadline); |
| 237 } | 234 } |
| 238 | 235 |
| 239 void _pruneClosedHandles(List<MojoHandleSignalsState> states) { | 236 void _pruneClosedHandles(List<List<int>> states) { |
| 240 List<int> closed = new List(); | 237 List<int> closed = new List(); |
| 241 for (var i = 0; i < _handles.length; i++) { | 238 for (var i = 0; i < _handles.length; i++) { |
| 242 if (states != null) { | 239 if (states != null) { |
| 243 var signals = new MojoHandleSignals(states[i].satisfied_signals); | 240 int signals = states[i][0]; |
| 244 if (signals.isPeerClosed) { | 241 if ((signals & kMojoSignalsPeerClosed) != 0) { |
| 245 closed.add(_handles[i]); | 242 closed.add(_handles[i]); |
| 246 } | 243 } |
| 247 } else { | 244 } else { |
| 248 _tempHandle._set(_handles[i]); | 245 List mwr = MojoHandleNatives.wait(_handles[i], kMojoSignalsAll, 0); |
| 249 MojoWaitResult mwr = _tempHandle.wait(MojoHandleSignals.kAll, 0); | 246 if ((mwr[0] != kMojoResultOk) && |
| 250 if ((!mwr.result.isOk) && (!mwr.result.isDeadlineExceeded)) { | 247 (mwr[0] != kMojoResultDeadlineExceeded)) { |
| 251 closed.add(_handles[i]); | 248 closed.add(_handles[i]); |
| 252 } | 249 } |
| 253 _tempHandle._set(MojoHandle.INVALID); | |
| 254 } | 250 } |
| 255 } | 251 } |
| 256 for (var h in closed) { | 252 for (var h in closed) { |
| 257 _close(h, null, pruning: true); | 253 _close(h, null, pruning: true); |
| 258 } | 254 } |
| 259 // '_close' updated the '_handles' array, so at this point the '_handles' | 255 // '_close' updated the '_handles' array, so at this point the '_handles' |
| 260 // array and the caller's 'states' array are mismatched. | 256 // array and the caller's 'states' array are mismatched. |
| 261 } | 257 } |
| 262 | 258 |
| 263 void _shutdownHandleWatcher(SendPort shutdownSendPort) { | 259 void _shutdownHandleWatcher(SendPort shutdownSendPort) { |
| 264 _shutdown = true; | 260 _shutdown = true; |
| 265 _tempHandle._set(_controlHandle); | 261 MojoHandleNatives.close(_controlHandle); |
| 266 _tempHandle.close(); | |
| 267 shutdownSendPort.send(null); | 262 shutdownSendPort.send(null); |
| 268 } | 263 } |
| 269 | 264 |
| 270 static MojoResult _sendControlData( | 265 static int _sendControlData( |
| 271 MojoHandle mojoHandle, SendPort port, int data) { | 266 int rawHandle, SendPort port, int data) { |
| 272 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); | 267 int controlHandle = MojoHandleWatcherNatives.getControlHandle(); |
| 273 if (controlHandle == MojoHandle.INVALID) { | 268 if (controlHandle == kMojoHandleInvalid) { |
| 274 return MojoResult.FAILED_PRECONDITION; | 269 return kMojoResultFailedPrecondition; |
| 275 } | 270 } |
| 276 | 271 |
| 277 int rawHandle = MojoHandle.INVALID; | 272 var result = MojoHandleWatcherNatives.sendControlData( |
| 278 if (mojoHandle != null) { | |
| 279 rawHandle = mojoHandle.h; | |
| 280 } | |
| 281 var result = _MojoHandleWatcherNatives.sendControlData( | |
| 282 controlHandle, rawHandle, port, data); | 273 controlHandle, rawHandle, port, data); |
| 283 return new MojoResult(result); | 274 return result; |
| 284 } | 275 } |
| 285 | 276 |
| 286 // Starts up the MojoHandleWatcher isolate. Should be called only once | 277 // Starts up the MojoHandleWatcher isolate. Should be called only once |
| 287 // per VM process. | 278 // per VM process. |
| 288 static Future<Isolate> _start() { | 279 static Future<Isolate> _start() { |
| 289 // Make a control message pipe, | 280 // Make a control message pipe, |
| 290 MojoMessagePipe pipe = new MojoMessagePipe(); | 281 List pipeEndpoints = MojoMessagePipeNatives.MojoCreateMessagePipe(0); |
| 291 int consumerHandle = pipe.endpoints[0].handle.h; | 282 assert(pipeEndpoints != null); |
| 292 int producerHandle = pipe.endpoints[1].handle.h; | 283 assert((pipeEndpoints is List) && (pipeEndpoints.length == 3)); |
| 284 assert(pipeEndpoints[0] == kMojoResultOk); |
| 285 |
| 286 int consumerHandle = pipeEndpoints[1]; |
| 287 int producerHandle = pipeEndpoints[2]; |
| 293 | 288 |
| 294 // Call setControlHandle with the other end. | 289 // Call setControlHandle with the other end. |
| 295 assert(producerHandle != MojoHandle.INVALID); | 290 assert(producerHandle != kMojoHandleInvalid); |
| 296 _MojoHandleWatcherNatives.setControlHandle(producerHandle); | 291 MojoHandleWatcherNatives.setControlHandle(producerHandle); |
| 297 | 292 |
| 298 // Spawn the handle watcher isolate with the MojoHandleWatcher, | 293 // Spawn the handle watcher isolate with the MojoHandleWatcher, |
| 299 return Isolate.spawn(_handleWatcherIsolate, consumerHandle); | 294 return Isolate.spawn(_handleWatcherIsolate, consumerHandle); |
| 300 } | 295 } |
| 301 | 296 |
| 302 // Causes the MojoHandleWatcher isolate to exit. Should be called only | 297 // Causes the MojoHandleWatcher isolate to exit. Should be called only |
| 303 // once per VM process. | 298 // once per VM process. |
| 304 static void _stop() { | 299 static void _stop() { |
| 305 // Create a port for notification that the handle watcher has shutdown. | 300 // Create a port for notification that the handle watcher has shutdown. |
| 306 var shutdownReceivePort = new ReceivePort(); | 301 var shutdownReceivePort = new ReceivePort(); |
| 307 var shutdownSendPort = shutdownReceivePort.sendPort; | 302 var shutdownSendPort = shutdownReceivePort.sendPort; |
| 308 | 303 |
| 309 // Send the shutdown command. | 304 // Send the shutdown command. |
| 310 _sendControlData(null, shutdownSendPort, _encodeCommand(SHUTDOWN)); | 305 _sendControlData( |
| 306 kMojoHandleInvalid, shutdownSendPort, _encodeCommand(SHUTDOWN)); |
| 311 | 307 |
| 312 // Close the control handle. | 308 // Close the control handle. |
| 313 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); | 309 int controlHandle = MojoHandleWatcherNatives.getControlHandle(); |
| 314 var handle = new MojoHandle(controlHandle); | 310 MojoHandleNatives.close(controlHandle); |
| 315 handle.close(); | |
| 316 | 311 |
| 317 // Invalidate the control handle. | 312 // Invalidate the control handle. |
| 318 _MojoHandleWatcherNatives.setControlHandle(MojoHandle.INVALID); | 313 MojoHandleWatcherNatives.setControlHandle(kMojoHandleInvalid); |
| 319 | 314 |
| 320 // Wait for the handle watcher isolate to exit. | 315 // Wait for the handle watcher isolate to exit. |
| 321 shutdownReceivePort.first.then((_) { | 316 shutdownReceivePort.first.then((_) { |
| 322 shutdownReceivePort.close(); | 317 shutdownReceivePort.close(); |
| 323 }); | 318 }); |
| 324 } | 319 } |
| 325 | 320 |
| 326 // If wait is true, returns a future that resolves only after the handle | 321 // If wait is true, returns a future that resolves only after the handle |
| 327 // has actually been closed by the handle watcher. Otherwise, returns a | 322 // has actually been closed by the handle watcher. Otherwise, returns a |
| 328 // future that resolves immediately. | 323 // future that resolves immediately. |
| 329 static Future<MojoResult> close(MojoHandle mojoHandle, {bool wait: false}) { | 324 static Future<int> close(int mojoHandle, {bool wait: false}) { |
| 330 assert(MojoHandle._removeUnclosedHandle(mojoHandle)); | 325 //assert(MojoHandle._removeUnclosedHandle(mojoHandle)); |
| 331 if (!wait) { | 326 if (!wait) { |
| 332 return new Future.value( | 327 return new Future.value( |
| 333 _sendControlData(mojoHandle, null, _encodeCommand(CLOSE))); | 328 _sendControlData(mojoHandle, null, _encodeCommand(CLOSE))); |
| 334 } | 329 } |
| 335 MojoResult result; | 330 int result; |
| 336 var completer = new Completer(); | 331 var completer = new Completer(); |
| 337 var rawPort = new RawReceivePort((_) { | 332 var rawPort = new RawReceivePort((_) { |
| 338 completer.complete(result); | 333 completer.complete(result); |
| 339 }); | 334 }); |
| 340 result = | 335 result = |
| 341 _sendControlData(mojoHandle, rawPort.sendPort, _encodeCommand(CLOSE)); | 336 _sendControlData(mojoHandle, rawPort.sendPort, _encodeCommand(CLOSE)); |
| 342 return completer.future.then((r) { | 337 return completer.future.then((r) { |
| 343 rawPort.close(); | 338 rawPort.close(); |
| 344 return r; | 339 return r; |
| 345 }); | 340 }); |
| 346 } | 341 } |
| 347 | 342 |
| 348 static MojoResult add(MojoHandle mojoHandle, SendPort port, int signals) { | 343 static int add(int mojoHandle, SendPort port, int signals) { |
| 349 return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals)); | 344 return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals)); |
| 350 } | 345 } |
| 351 | 346 |
| 352 static MojoResult remove(MojoHandle mojoHandle) { | 347 static int remove(int mojoHandle) { |
| 353 return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); | 348 return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); |
| 354 } | 349 } |
| 355 | 350 |
| 356 static MojoResult timer(Object ignored, SendPort port, int deadline) { | 351 static int timer(Object ignored, SendPort port, int deadline) { |
| 357 // The deadline will be unwrapped before sending to the handle watcher. | 352 // The deadline will be unwrapped before sending to the handle watcher. |
| 358 return _sendControlData( | 353 return _sendControlData(deadline, port, _encodeCommand(TIMER)); |
| 359 new MojoHandle._internal(deadline), port, _encodeCommand(TIMER)); | |
| 360 } | 354 } |
| 361 } | 355 } |
| OLD | NEW |