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 core; |
6 | 6 |
7 class _MojoHandleWatcherNatives { | 7 class _MojoHandleWatcherNatives { |
8 static int sendControlData( | 8 static int sendControlData( |
9 int controlHandle, int mojoHandle, SendPort port, int data) | 9 int controlHandle, int mojoHandle, SendPort port, int data) |
10 native "MojoHandleWatcher_SendControlData"; | 10 native "MojoHandleWatcher_SendControlData"; |
(...skipping 15 matching lines...) Expand all Loading... |
26 // | 26 // |
27 // add(handle, port, signals) - Instructs the MojoHandleWatcher isolate to add | 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 | 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 | 29 // isolate only for the events specified by 'signals' using the send port |
30 // 'port' | 30 // 'port' |
31 // | 31 // |
32 // remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle' | 32 // remove(handle) - Instructs the MojoHandleWatcher isolate to remove 'handle' |
33 // from the set of handles it watches. This allows the application isolate | 33 // from the set of handles it watches. This allows the application isolate |
34 // to, e.g., pause the stream of events. | 34 // to, e.g., pause the stream of events. |
35 // | 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 | 36 // close(handle) - Notifies the HandleWatcherIsolate that a handle it is |
41 // watching should be removed from its set and closed. | 37 // watching should be removed from its set and closed. |
42 class MojoHandleWatcher { | 38 class MojoHandleWatcher { |
43 // Control commands. | 39 // Control commands. |
44 static const int ADD = 0; | 40 static const int ADD = 0; |
45 static const int REMOVE = 1; | 41 static const int REMOVE = 1; |
46 static const int TOGGLE_WRITE = 2; | 42 static const int CLOSE = 2; |
47 static const int CLOSE = 3; | 43 static const int TIMER = 3; |
48 static const int TIMER = 4; | 44 static const int SHUTDOWN = 4; |
49 static const int SHUTDOWN = 5; | |
50 | 45 |
51 static int _encodeCommand(int cmd, [int signals = 0]) => | 46 static int _encodeCommand(int cmd, [int signals = 0]) => |
52 (cmd << 2) | (signals & MojoHandleSignals.READWRITE); | 47 (cmd << 2) | (signals & MojoHandleSignals.kReadWrite); |
53 static int _decodeCommand(int cmd) => cmd >> 2; | 48 static int _decodeCommand(int cmd) => cmd >> 2; |
54 | 49 |
55 // The Mojo handle over which control messages are sent. | 50 // The Mojo handle over which control messages are sent. |
56 int _controlHandle; | 51 int _controlHandle; |
57 | 52 |
58 // Whether the handle watcher should shut down. | 53 // Whether the handle watcher should shut down. |
59 bool _shutdown; | 54 bool _shutdown; |
60 | 55 |
61 // The list of handles being watched. | 56 // The list of handles being watched. |
62 List<int> _handles; | 57 List<int> _handles; |
63 int _handleCount; | 58 int _handleCount; |
64 | 59 |
65 // A port for each handle on which to send events back to the isolate that | 60 // A port for each handle on which to send events back to the isolate that |
66 // owns the handle. | 61 // owns the handle. |
67 List<SendPort> _ports; | 62 List<SendPort> _ports; |
68 | 63 |
69 // The signals that we care about for each handle. | 64 // The signals that we care about for each handle. |
70 List<int> _signals; | 65 List<int> _signals; |
71 | 66 |
72 // A mapping from Mojo handles to their indices in _handles. | 67 // A mapping from Mojo handles to their indices in _handles. |
73 Map<int, int> _handleIndices; | 68 Map<int, int> _handleIndices; |
74 | 69 |
75 // Since we are not storing wrapped handles, a dummy handle for when we need | 70 // Since we are not storing wrapped handles, a dummy handle for when we need |
76 // a RawMojoHandle. | 71 // a MojoHandle. |
77 RawMojoHandle _tempHandle; | 72 MojoHandle _tempHandle; |
78 | 73 |
79 // Priority queue of timers registered with the watcher. | 74 // Priority queue of timers registered with the watcher. |
80 TimerQueue _timerQueue; | 75 TimerQueue _timerQueue; |
81 | 76 |
82 MojoHandleWatcher(this._controlHandle) : | 77 MojoHandleWatcher(this._controlHandle) : |
83 _shutdown = false, | 78 _shutdown = false, |
84 _handles = new List<int>(), | 79 _handles = new List<int>(), |
85 _ports = new List<SendPort>(), | 80 _ports = new List<SendPort>(), |
86 _signals = new List<int>(), | 81 _signals = new List<int>(), |
87 _handleIndices = new Map<int, int>(), | 82 _handleIndices = new Map<int, int>(), |
88 _handleCount = 1, | 83 _handleCount = 1, |
89 _tempHandle = new RawMojoHandle(RawMojoHandle.INVALID), | 84 _tempHandle = new MojoHandle(MojoHandle.INVALID), |
90 _timerQueue = new TimerQueue() { | 85 _timerQueue = new TimerQueue() { |
91 // Setup control handle. | 86 // Setup control handle. |
92 _handles.add(_controlHandle); | 87 _handles.add(_controlHandle); |
93 _ports.add(null); // There is no port for the control handle. | 88 _ports.add(null); // There is no port for the control handle. |
94 _signals.add(MojoHandleSignals.READABLE); | 89 _signals.add(MojoHandleSignals.kReadable); |
95 _handleIndices[_controlHandle] = 0; | 90 _handleIndices[_controlHandle] = 0; |
96 } | 91 } |
97 | 92 |
98 static void _handleWatcherIsolate(int consumerHandle) { | 93 static void _handleWatcherIsolate(int consumerHandle) { |
99 MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); | 94 MojoHandleWatcher watcher = new MojoHandleWatcher(consumerHandle); |
100 while (!watcher._shutdown) { | 95 while (!watcher._shutdown) { |
101 int deadline = watcher._processTimerDeadlines(); | 96 int deadline = watcher._processTimerDeadlines(); |
102 int res = RawMojoHandle.waitMany(watcher._handles, | 97 MojoWaitManyResult mwmr = MojoHandle.waitMany( |
103 watcher._signals, | 98 watcher._handles, watcher._signals, deadline); |
104 deadline); | 99 if (mwmr.result.isOk && mwmr.index == 0) { |
105 if (res == 0) { | |
106 watcher._handleControlMessage(); | 100 watcher._handleControlMessage(); |
107 } else if (res > 0) { | 101 } else if (mwmr.result.isOk && (mwmr.index > 0)) { |
108 int handle = watcher._handles[res]; | 102 int handle = watcher._handles[mwmr.index]; |
109 // Route event. | 103 // Route event. |
110 watcher._routeEvent(res); | 104 watcher._routeEvent(mwmr.index); |
111 // Remove the handle from the list. | 105 // Remove the handle from the list. |
112 watcher._removeHandle(handle); | 106 watcher._removeHandle(handle); |
113 } else if (res != MojoResult.kDeadlineExceeded) { | 107 } else if (!mwmr.result.isDeadlineExceeded) { |
114 // Some handle was closed, but not by us. | 108 // Some handle was closed, but not by us. |
115 // We have to go through the list and find it. | 109 // Find it and close it on our side. |
116 watcher._pruneClosedHandles(); | 110 watcher._pruneClosedHandles(mwmr.states); |
117 } | 111 } |
118 } | 112 } |
119 } | 113 } |
120 | 114 |
121 void _routeEvent(int idx) { | 115 void _routeEvent(int idx) { |
122 int client_handle = _handles[idx]; | 116 int client_handle = _handles[idx]; |
123 int signals = _signals[idx]; | 117 var signals = new MojoHandleSignals(_signals[idx]); |
124 SendPort port = _ports[idx]; | 118 SendPort port = _ports[idx]; |
125 | 119 |
126 _tempHandle.h = client_handle; | 120 _tempHandle.h = client_handle; |
127 bool readyWrite = | 121 bool readyWrite = signals.isWritable && _tempHandle.readyWrite; |
128 MojoHandleSignals.isWritable(signals) && _tempHandle.readyWrite(); | 122 bool readyRead = signals.isReadable && _tempHandle.readyRead; |
129 bool readyRead = | 123 _tempHandle.h = MojoHandle.INVALID; |
130 MojoHandleSignals.isReadable(signals) && _tempHandle.readyRead(); | 124 |
131 if (readyRead && readyWrite) { | 125 var event = MojoHandleSignals.NONE; |
132 port.send(MojoHandleSignals.READWRITE); | 126 event += readyRead ? MojoHandleSignals.READABLE : MojoHandleSignals.NONE; |
133 } else if (readyWrite) { | 127 event += readyWrite ? MojoHandleSignals.WRITABLE : MojoHandleSignals.NONE; |
134 port.send(MojoHandleSignals.WRITABLE); | 128 port.send([signals.value, event.value]); |
135 } else if (readyRead) { | |
136 port.send(MojoHandleSignals.READABLE); | |
137 } | |
138 _tempHandle.h = RawMojoHandle.INVALID; | |
139 } | 129 } |
140 | 130 |
141 void _handleControlMessage() { | 131 void _handleControlMessage() { |
142 List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle); | 132 List result = _MojoHandleWatcherNatives.recvControlData(_controlHandle); |
143 // result[0] = mojo handle if any, or a timer deadline in milliseconds. | 133 // result[0] = mojo handle if any, or a timer deadline in milliseconds. |
144 // result[1] = SendPort if any. | 134 // result[1] = SendPort if any. |
145 // result[2] = command << 2 | WRITABLE | READABLE | 135 // result[2] = command << 2 | WRITABLE | READABLE |
146 | 136 |
147 int signals = result[2] & MojoHandleSignals.READWRITE; | 137 var signals = new MojoHandleSignals( |
| 138 result[2] & MojoHandleSignals.kReadWrite); |
148 int command = _decodeCommand(result[2]); | 139 int command = _decodeCommand(result[2]); |
149 switch (command) { | 140 switch (command) { |
150 case ADD: | 141 case ADD: |
151 _addHandle(result[0], result[1], signals); | 142 _addHandle(result[0], result[1], signals); |
152 break; | 143 break; |
153 case REMOVE: | 144 case REMOVE: |
154 _removeHandle(result[0]); | 145 _removeHandle(result[0]); |
155 break; | 146 break; |
156 case TOGGLE_WRITE: | |
157 _toggleWrite(result[0]); | |
158 break; | |
159 case CLOSE: | 147 case CLOSE: |
160 _close(result[0]); | 148 _close(result[0]); |
161 break; | 149 break; |
162 case TIMER: | 150 case TIMER: |
163 _timer(result[1], result[0]); | 151 _timer(result[1], result[0]); |
164 break; | 152 break; |
165 case SHUTDOWN: | 153 case SHUTDOWN: |
166 _shutdownHandleWatcher(); | 154 _shutdownHandleWatcher(result[1]); |
167 break; | 155 break; |
168 default: | 156 default: |
169 throw new Exception("Invalid Command: $command"); | 157 throw "Invalid Command: $command"; |
170 break; | 158 break; |
171 } | 159 } |
172 } | 160 } |
173 | 161 |
174 void _addHandle(int mojoHandle, SendPort port, int signals) { | 162 void _addHandle(int mojoHandle, SendPort port, MojoHandleSignals signals) { |
175 _handles.add(mojoHandle); | 163 int idx = _handleIndices[mojoHandle]; |
176 _ports.add(port); | 164 if (idx == null) { |
177 _signals.add(signals & MojoHandleSignals.READWRITE); | 165 _handles.add(mojoHandle); |
178 _handleIndices[mojoHandle] = _handleCount; | 166 _ports.add(port); |
179 _handleCount++; | 167 _signals.add(signals.value); |
| 168 _handleIndices[mojoHandle] = _handleCount; |
| 169 _handleCount++; |
| 170 } else { |
| 171 assert(_ports[idx] == port); |
| 172 assert(_handles[idx] == mojoHandle); |
| 173 _signals[idx] |= signals.value; |
| 174 } |
180 } | 175 } |
181 | 176 |
182 void _removeHandle(int mojoHandle) { | 177 void _removeHandle(int mojoHandle) { |
183 int idx = _handleIndices[mojoHandle]; | 178 int idx = _handleIndices[mojoHandle]; |
184 if (idx == null) { | 179 if (idx == null) { |
185 throw new Exception("Remove on a non-existent handle: idx = $idx."); | 180 throw "Remove on a non-existent handle: idx = $idx."; |
186 } | 181 } |
187 if (idx == 0) { | 182 if (idx == 0) { |
188 throw new Exception("The control handle (idx = 0) cannot be removed."); | 183 throw "The control handle (idx = 0) cannot be removed."; |
189 } | 184 } |
190 // We don't use List.removeAt so that we know how to fix-up _handleIndices. | 185 // We don't use List.removeAt so that we know how to fix-up _handleIndices. |
191 if (idx == _handleCount - 1) { | 186 if (idx == _handleCount - 1) { |
192 int handle = _handles[idx]; | 187 int handle = _handles[idx]; |
193 _handleIndices[handle] = null; | 188 _handleIndices[handle] = null; |
194 _handles.removeLast(); | 189 _handles.removeLast(); |
195 _signals.removeLast(); | 190 _signals.removeLast(); |
196 _ports.removeLast(); | 191 _ports.removeLast(); |
197 _handleCount--; | 192 _handleCount--; |
198 } else { | 193 } else { |
199 int last = _handleCount - 1; | 194 int last = _handleCount - 1; |
| 195 _handleIndices[_handles[idx]] = null; |
200 _handles[idx] = _handles[last]; | 196 _handles[idx] = _handles[last]; |
201 _signals[idx] = _signals[last]; | 197 _signals[idx] = _signals[last]; |
202 _ports[idx] = _ports[last]; | 198 _ports[idx] = _ports[last]; |
203 _handles.removeLast(); | 199 _handles.removeLast(); |
204 _signals.removeLast(); | 200 _signals.removeLast(); |
205 _ports.removeLast(); | 201 _ports.removeLast(); |
206 _handleIndices[_handles[idx]] = idx; | 202 _handleIndices[_handles[idx]] = idx; |
207 _handleCount--; | 203 _handleCount--; |
208 } | 204 } |
209 } | 205 } |
210 | 206 |
211 void _close(int mojoHandle, {bool pruning : false}) { | 207 void _close(int mojoHandle, {bool pruning : false}) { |
212 int idx = _handleIndices[mojoHandle]; | 208 int idx = _handleIndices[mojoHandle]; |
213 if (idx == null) { | 209 if (idx == null) { |
214 throw new Exception("Close on a non-existent handle: idx = $idx."); | 210 // A client may request to close a handle that has already been closed on |
| 211 // the other side and pruned, but before receiving notification from the |
| 212 // handle watcher. |
| 213 return; |
215 } | 214 } |
216 if (idx == 0) { | 215 if (idx == 0) { |
217 throw new Exception("The control handle (idx = 0) cannot be closed."); | 216 throw "The control handle (idx = 0) cannot be closed."; |
218 } | 217 } |
219 _tempHandle.h = _handles[idx]; | 218 _tempHandle.h = _handles[idx]; |
220 _tempHandle.close(); | 219 _tempHandle.close(); |
221 _tempHandle.h = RawMojoHandle.INVALID; | 220 _tempHandle.h = MojoHandle.INVALID; |
222 if (pruning) { | 221 if (pruning) { |
223 // If this handle is being pruned, notify the application isolate | 222 // If this handle is being pruned, notify the application isolate |
224 // by sending MojoHandleSignals.NONE. | 223 // by sending MojoHandleSignals.PEER_CLOSED. |
225 _ports[idx].send(MojoHandleSignals.NONE); | 224 _ports[idx].send([_signals[idx], MojoHandleSignals.kPeerClosed]); |
226 } | 225 } |
227 _removeHandle(mojoHandle); | 226 _removeHandle(mojoHandle); |
228 } | 227 } |
229 | 228 |
230 // Returns the next timer deadline in units of microseconds from 'now'. | 229 // Returns the next timer deadline in units of microseconds from 'now'. |
231 int _processTimerDeadlines() { | 230 int _processTimerDeadlines() { |
232 int now = (new DateTime.now()).millisecondsSinceEpoch; | 231 int now = (new DateTime.now()).millisecondsSinceEpoch; |
233 while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { | 232 while (_timerQueue.hasTimer && (now >= _timerQueue.currentTimeout)) { |
234 _timerQueue.currentPort.send(null); | 233 _timerQueue.currentPort.send(null); |
235 _timerQueue.removeCurrent(); | 234 _timerQueue.removeCurrent(); |
236 now = (new DateTime.now()).millisecondsSinceEpoch; | 235 now = (new DateTime.now()).millisecondsSinceEpoch; |
237 } | 236 } |
238 return _timerQueue.hasTimer ? (_timerQueue.currentTimeout - now) * 1000 | 237 return _timerQueue.hasTimer ? (_timerQueue.currentTimeout - now) * 1000 |
239 : RawMojoHandle.DEADLINE_INDEFINITE; | 238 : MojoHandle.DEADLINE_INDEFINITE; |
240 } | 239 } |
241 | 240 |
242 void _timer(SendPort port, int deadline) { | 241 void _timer(SendPort port, int deadline) { |
243 _timerQueue.updateTimer(port, deadline); | 242 _timerQueue.updateTimer(port, deadline); |
244 } | 243 } |
245 | 244 |
246 void _toggleWrite(int mojoHandle) { | 245 void _pruneClosedHandles(List<MojoHandleSignalsState> states) { |
247 int idx = _handleIndices[mojoHandle]; | |
248 if (idx == null) { | |
249 throw new Exception( | |
250 "Toggle write on a non-existent handle: $mojoHandle."); | |
251 } | |
252 if (idx == 0) { | |
253 throw new Exception("The control handle (idx = 0) cannot be toggled."); | |
254 } | |
255 _signals[idx] = MojoHandleSignals.toggleWrite(_signals[idx]); | |
256 } | |
257 | |
258 void _pruneClosedHandles() { | |
259 List<int> closed = new List(); | 246 List<int> closed = new List(); |
260 for (var h in _handles) { | 247 for (var i = 0; i < _handles.length; i++) { |
261 _tempHandle.h = h; | 248 if (states != null) { |
262 MojoResult res = _tempHandle.wait(MojoHandleSignals.READWRITE, 0); | 249 var signals = new MojoHandleSignals(states[i].satisfied_signals); |
263 if ((!res.isOk) && (!res.isDeadlineExceeded)) { | 250 if (signals.isPeerClosed) { |
264 closed.add(h); | 251 closed.add(_handles[i]); |
| 252 } |
| 253 } else { |
| 254 _tempHandle.h = _handles[i]; |
| 255 MojoWaitResult mwr = _tempHandle.wait(MojoHandleSignals.kReadWrite, 0); |
| 256 if ((!mwr.result.isOk) && (!mwr.result.isDeadlineExceeded)) { |
| 257 closed.add(_handles[i]); |
| 258 } |
| 259 _tempHandle.h = MojoHandle.INVALID; |
265 } | 260 } |
266 _tempHandle.h = RawMojoHandle.INVALID; | |
267 } | 261 } |
268 for (var h in closed) { | 262 for (var h in closed) { |
269 _close(h, pruning: true); | 263 _close(h, pruning: true); |
270 } | 264 } |
| 265 // '_close' updated the '_handles' array, so at this point the '_handles' |
| 266 // array and the caller's 'states' array are mismatched. |
271 } | 267 } |
272 | 268 |
273 void _shutdownHandleWatcher() { | 269 void _shutdownHandleWatcher(SendPort shutdownSendPort) { |
274 _shutdown = true; | 270 _shutdown = true; |
275 _tempHandle.h = _controlHandle; | 271 _tempHandle.h = _controlHandle; |
276 _tempHandle.close(); | 272 _tempHandle.close(); |
277 _tempHandle.h = RawMojoHandle.INVALID; | 273 _tempHandle.h = MojoHandle.INVALID; |
| 274 shutdownSendPort.send(null); |
278 } | 275 } |
279 | 276 |
280 static MojoResult _sendControlData(RawMojoHandle mojoHandle, | 277 static MojoResult _sendControlData(MojoHandle mojoHandle, |
281 SendPort port, | 278 SendPort port, |
282 int data) { | 279 int data) { |
283 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); | 280 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); |
284 if (controlHandle == RawMojoHandle.INVALID) { | 281 if (controlHandle == MojoHandle.INVALID) { |
285 throw new Exception("Found invalid control handle"); | 282 return MojoResult.FAILED_PRECONDITION; |
286 } | 283 } |
287 | 284 |
288 int rawHandle = RawMojoHandle.INVALID; | 285 int rawHandle = MojoHandle.INVALID; |
289 if (mojoHandle != null) { | 286 if (mojoHandle != null) { |
290 rawHandle = mojoHandle.h; | 287 rawHandle = mojoHandle.h; |
291 } | 288 } |
292 var result = _MojoHandleWatcherNatives.sendControlData( | 289 var result = _MojoHandleWatcherNatives.sendControlData( |
293 controlHandle, rawHandle, port, data); | 290 controlHandle, rawHandle, port, data); |
294 return new MojoResult(result); | 291 return new MojoResult(result); |
295 } | 292 } |
296 | 293 |
297 static Future<Isolate> Start() { | 294 static Future<Isolate> Start() { |
298 // Make a control message pipe, | 295 // Make a control message pipe, |
299 MojoMessagePipe pipe = new MojoMessagePipe(); | 296 MojoMessagePipe pipe = new MojoMessagePipe(); |
300 int consumerHandle = pipe.endpoints[0].handle.h; | 297 int consumerHandle = pipe.endpoints[0].handle.h; |
301 int producerHandle = pipe.endpoints[1].handle.h; | 298 int producerHandle = pipe.endpoints[1].handle.h; |
302 | 299 |
303 // Call setControlHandle with the other end. | 300 // Call setControlHandle with the other end. |
| 301 assert(producerHandle != MojoHandle.INVALID); |
304 _MojoHandleWatcherNatives.setControlHandle(producerHandle); | 302 _MojoHandleWatcherNatives.setControlHandle(producerHandle); |
305 | 303 |
306 // Spawn the handle watcher isolate with the MojoHandleWatcher, | 304 // Spawn the handle watcher isolate with the MojoHandleWatcher, |
307 return Isolate.spawn(_handleWatcherIsolate, consumerHandle); | 305 return Isolate.spawn(_handleWatcherIsolate, consumerHandle); |
308 } | 306 } |
309 | 307 |
310 static void Stop() { | 308 static void Stop() { |
| 309 // Create a port for notification that the handle watcher has shutdown. |
| 310 var shutdownReceivePort = new ReceivePort(); |
| 311 var shutdownSendPort = shutdownReceivePort.sendPort; |
| 312 |
311 // Send the shutdown command. | 313 // Send the shutdown command. |
312 _sendControlData(null, null, _encodeCommand(SHUTDOWN)); | 314 _sendControlData(null, shutdownSendPort, _encodeCommand(SHUTDOWN)); |
313 | 315 |
314 // Close the control handle. | 316 // Close the control handle. |
315 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); | 317 int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); |
316 var handle = new RawMojoHandle(controlHandle); | 318 var handle = new MojoHandle(controlHandle); |
317 handle.close(); | 319 handle.close(); |
318 | 320 |
319 // Invalidate the control handle. | 321 // Invalidate the control handle. |
320 _MojoHandleWatcherNatives.setControlHandle(RawMojoHandle.INVALID); | 322 _MojoHandleWatcherNatives.setControlHandle(MojoHandle.INVALID); |
| 323 |
| 324 // Wait for the handle watcher isolate to exit. |
| 325 shutdownReceivePort.first.then((_) { |
| 326 shutdownReceivePort.close(); |
| 327 }); |
321 } | 328 } |
322 | 329 |
323 static MojoResult close(RawMojoHandle mojoHandle) { | 330 static MojoResult close(MojoHandle mojoHandle) { |
324 return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE)); | 331 return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE)); |
325 } | 332 } |
326 | 333 |
327 static MojoResult toggleWrite(RawMojoHandle mojoHandle) { | 334 static MojoResult add(MojoHandle mojoHandle, SendPort port, int signals) { |
328 return _sendControlData(mojoHandle, null, _encodeCommand(TOGGLE_WRITE)); | |
329 } | |
330 | |
331 static MojoResult add(RawMojoHandle mojoHandle, SendPort port, int signals) { | |
332 return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals)); | 335 return _sendControlData(mojoHandle, port, _encodeCommand(ADD, signals)); |
333 } | 336 } |
334 | 337 |
335 static MojoResult remove(RawMojoHandle mojoHandle) { | 338 static MojoResult remove(MojoHandle mojoHandle) { |
336 return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); | 339 return _sendControlData(mojoHandle, null, _encodeCommand(REMOVE)); |
337 } | 340 } |
338 | 341 |
339 static MojoResult timer(SendPort port, int deadline) { | 342 static MojoResult timer(SendPort port, int deadline) { |
340 // The deadline will be unwrapped before sending to the handle watcher. | 343 // The deadline will be unwrapped before sending to the handle watcher. |
341 return _sendControlData( | 344 return _sendControlData( |
342 new RawMojoHandle(deadline), port, _encodeCommand(TIMER)); | 345 new MojoHandle(deadline), port, _encodeCommand(TIMER)); |
343 } | 346 } |
344 } | 347 } |
OLD | NEW |