Chromium Code Reviews| 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 _MojoHandleNatives { | 7 class _MojoHandleNatives { |
| 8 static int register(MojoHandle handle) native "MojoHandle_Register"; | 8 static int register(MojoHandle handle) native "MojoHandle_Register"; |
| 9 static int close(int handle) native "MojoHandle_Close"; | 9 static int close(int handle) native "MojoHandle_Close"; |
| 10 static int wait(int handle, int signals, int deadline) | 10 static int wait(int handle, int signals, int deadline) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 int result = _MojoHandleNatives.close(h); | 27 int result = _MojoHandleNatives.close(h); |
| 28 h = INVALID; | 28 h = INVALID; |
| 29 return new MojoResult(result); | 29 return new MojoResult(result); |
| 30 } | 30 } |
| 31 | 31 |
| 32 MojoResult wait(int signals, int deadline) { | 32 MojoResult wait(int signals, int deadline) { |
| 33 int result = _MojoHandleNatives.wait(h, signals, deadline); | 33 int result = _MojoHandleNatives.wait(h, signals, deadline); |
| 34 return new MojoResult(result); | 34 return new MojoResult(result); |
| 35 } | 35 } |
| 36 | 36 |
| 37 bool _ready(int signal) { | 37 bool _ready(MojoHandleSignals signal) { |
| 38 MojoResult res = wait(signal, 0); | 38 MojoResult res = wait(signal.value, 0); |
| 39 switch (res) { | 39 switch (res) { |
| 40 case MojoResult.OK: | 40 case MojoResult.OK: |
| 41 return true; | 41 return true; |
| 42 case MojoResult.DEADLINE_EXCEEDED: | 42 case MojoResult.DEADLINE_EXCEEDED: |
| 43 case MojoResult.CANCELLED: | 43 case MojoResult.CANCELLED: |
| 44 case MojoResult.INVALID_ARGUMENT: | 44 case MojoResult.INVALID_ARGUMENT: |
| 45 case MojoResult.FAILED_PRECONDITION: | 45 case MojoResult.FAILED_PRECONDITION: |
| 46 return false; | 46 return false; |
| 47 default: | 47 default: |
| 48 // Should be unreachable. | 48 // Should be unreachable. |
| 49 throw new Exception("Unreachable"); | 49 throw "Unexpected result $res for wait on $h"; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 bool readyRead() => _ready(MojoHandleSignals.READABLE); | 53 bool get readyRead => _ready(MojoHandleSignals.READABLE); |
| 54 bool readyWrite() => _ready(MojoHandleSignals.WRITABLE); | 54 bool get readyWrite => _ready(MojoHandleSignals.WRITABLE); |
| 55 | 55 |
| 56 static int waitMany(List<int> handles, | 56 static int waitMany(List<int> handles, |
| 57 List<int> signals, | 57 List<int> signals, |
| 58 int deadline) { | 58 int deadline) { |
| 59 if (handles.length != signals.length) { | 59 if (handles.length != signals.length) { |
| 60 return MojoResult.kInvalidArgument; | 60 return MojoResult.kInvalidArgument; |
| 61 } | 61 } |
| 62 return _MojoHandleNatives.waitMany( | 62 return _MojoHandleNatives.waitMany( |
| 63 handles, signals, handles.length, deadline); | 63 handles, signals, handles.length, deadline); |
| 64 } | 64 } |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 87 | 87 |
| 88 // The send port that we give to the handle watcher to notify us of handle | 88 // The send port that we give to the handle watcher to notify us of handle |
| 89 // events. | 89 // events. |
| 90 SendPort _sendPort; | 90 SendPort _sendPort; |
| 91 | 91 |
| 92 // The receive port on which we listen and receive events from the handle | 92 // The receive port on which we listen and receive events from the handle |
| 93 // watcher. | 93 // watcher. |
| 94 ReceivePort _receivePort; | 94 ReceivePort _receivePort; |
| 95 | 95 |
| 96 // The signals on this handle that we're interested in. | 96 // The signals on this handle that we're interested in. |
| 97 int _signals; | 97 MojoHandleSignals _signals; |
| 98 | 98 |
| 99 // Whether the handle has been added to the handle watcher. | 99 // Whether listen has been called. |
| 100 bool _eventHandlerAdded; | 100 bool _isListening; |
| 101 | 101 |
| 102 MojoHandle(this._handle) : | 102 MojoHandle(RawMojoHandle handle, |
| 103 _signals = MojoHandleSignals.READABLE, | 103 [MojoHandleSignals signals = MojoHandleSignals.READABLE]) : |
| 104 _eventHandlerAdded = false { | 104 _handle = handle, |
| 105 _signals = signals, | |
| 106 _isListening = false { | |
| 105 MojoResult result = RawMojoHandle.register(this); | 107 MojoResult result = RawMojoHandle.register(this); |
| 106 if (!result.isOk) { | 108 if (!result.isOk) { |
| 107 throw new Exception("Failed to register the MojoHandle"); | 109 throw "Failed to register the MojoHandle: $result."; |
| 108 } | 110 } |
| 109 } | 111 } |
| 110 | 112 |
| 111 void close() { | 113 void close() { |
| 112 if (_eventHandlerAdded) { | 114 if (_handle != null) { |
| 113 MojoHandleWatcher.close(_handle); | 115 MojoHandleWatcher.close(_handle); |
| 114 _eventHandlerAdded = false; | |
| 115 } else { | |
| 116 // If we're not in the handle watcher, then close the handle manually. | |
| 117 _handle.close(); | 116 _handle.close(); |
| 117 _handle = null; | |
| 118 } | 118 } |
| 119 if (_receivePort != null) { | 119 if (_receivePort != null) { |
| 120 _receivePort.close(); | 120 _receivePort.close(); |
| 121 _receivePort = null; | |
| 121 } | 122 } |
| 122 } | 123 } |
| 123 | 124 |
| 124 // We wrap the callback provided by clients in listen() with some code to | 125 StreamSubscription<List<int>> listen( |
| 125 // handle adding and removing the handle to/from the handle watcher. Because | 126 void onData(List event), |
| 126 // the handle watcher removes this handle whenever it receives an event, | |
| 127 // we have to re-add it when the callback is finished. | |
| 128 Function _onDataClosure(origOnData) { | |
| 129 return ((int event) { | |
| 130 // The handle watcher removes this handle from its set on an event. | |
| 131 _eventHandlerAdded = false; | |
| 132 origOnData(event); | |
| 133 | |
| 134 // The callback could have closed the handle. If so, don't add it back to | |
| 135 // the MojoHandleWatcher. | |
| 136 if (_handle.isValid) { | |
| 137 assert(!_eventHandlerAdded); | |
| 138 var res = MojoHandleWatcher.add(_handle, _sendPort, _signals); | |
| 139 if (!res.isOk) { | |
| 140 throw new Exception("Failed to re-add handle: $res"); | |
| 141 } | |
| 142 _eventHandlerAdded = true; | |
| 143 } | |
| 144 }); | |
| 145 } | |
| 146 | |
| 147 StreamSubscription<int> listen( | |
| 148 void onData(int event), | |
| 149 {Function onError, void onDone(), bool cancelOnError}) { | 127 {Function onError, void onDone(), bool cancelOnError}) { |
| 128 if (_isListening) { | |
| 129 throw "Listen has already been called: $_handle."; | |
| 130 } | |
| 150 _receivePort = new ReceivePort(); | 131 _receivePort = new ReceivePort(); |
| 151 _sendPort = _receivePort.sendPort; | 132 _sendPort = _receivePort.sendPort; |
| 152 _controller = new StreamController(sync: true, | 133 _controller = new StreamController(sync: true, |
| 153 onListen: _onSubscriptionStateChange, | 134 onListen: _onSubscriptionStateChange, |
| 154 onCancel: _onSubscriptionStateChange, | 135 onCancel: _onSubscriptionStateChange, |
| 155 onPause: _onPauseStateChange, | 136 onPause: _onPauseStateChange, |
| 156 onResume: _onPauseStateChange); | 137 onResume: _onPauseStateChange); |
| 157 _controller.addStream(_receivePort); | 138 _controller.addStream(_receivePort); |
| 158 | 139 |
| 159 assert(!_eventHandlerAdded); | 140 if (_signals != MojoHandleSignals.NONE) { |
| 160 var res = MojoHandleWatcher.add(_handle, _sendPort, _signals); | 141 var res = MojoHandleWatcher.add(_handle, _sendPort, _signals.value); |
| 161 if (!res.isOk) { | 142 if (!res.isOk) { |
| 162 throw new Exception("MojoHandleWatcher add failed: $res"); | 143 throw "MojoHandleWatcher add failed: $res"; |
| 144 } | |
| 163 } | 145 } |
| 164 _eventHandlerAdded = true; | |
| 165 | 146 |
| 147 _isListening = true; | |
| 166 return _controller.stream.listen( | 148 return _controller.stream.listen( |
| 167 _onDataClosure(onData), | 149 onData, |
| 168 onError: onError, | 150 onError: onError, |
| 169 onDone: onDone, | 151 onDone: onDone, |
| 170 cancelOnError: cancelOnError); | 152 cancelOnError: cancelOnError); |
| 171 } | 153 } |
| 172 | 154 |
| 173 bool writeEnabled() => MojoHandleSignals.isWritable(_signals); | 155 bool writeEnabled() => MojoHandleSignals.isWritable(_signals); |
| 156 bool readEnabled() => MojoHandleSignals.isReadable(_signals); | |
|
siva
2014/12/29 23:20:44
These should also just be getters?
zra
2014/12/30 16:29:33
Yes. These aren't actually be used anywhere though
| |
| 174 | 157 |
| 175 void toggleWriteEvents() { | 158 void enableSignals(MojoHandleSignals signals) { |
| 176 _signals = MojoHandleSignals.toggleWrite(_signals); | 159 _signals = signals; |
| 177 if (_eventHandlerAdded) { | 160 if (!_isListening) { |
| 178 var res = MojoHandleWatcher.toggleWrite(_handle); | 161 throw "Cannot enable signals if listen() has not been called."; |
| 179 if (!res.isOk) { | 162 } |
| 180 throw new Exception("MojoHandleWatcher failed to toggle write: $res"); | 163 var res = MojoHandleWatcher.add(_handle, _sendPort, signals.value); |
| 181 } | 164 if (!res.isOk) { |
| 165 throw "MojoHandleWatcher add failed: $res"; | |
| 182 } | 166 } |
| 183 } | 167 } |
| 184 | 168 |
| 185 void enableWriteEvents() { | 169 void enableReadEvents() => enableSignals(MojoHandleSignals.READABLE); |
| 186 assert(!writeEnabled()); | 170 void enableWriteEvents() => enableSignals(MojoHandleSignals.WRITABLE); |
| 187 toggleWriteEvents(); | 171 void enableAllEvents() => enableSignals(MojoHandleSignals.READWRITE); |
| 188 } | |
| 189 | |
| 190 void disableWriteEvents() { | |
| 191 assert(writeEnabled()); | |
| 192 toggleWriteEvents(); | |
| 193 } | |
| 194 | 172 |
| 195 void _onSubscriptionStateChange() { | 173 void _onSubscriptionStateChange() { |
| 196 if (!_controller.hasListener) { | 174 if (!_controller.hasListener) { |
| 197 close(); | 175 close(); |
| 198 } | 176 } |
| 199 } | 177 } |
| 200 | 178 |
| 201 void _onPauseStateChange() { | 179 void _onPauseStateChange() { |
| 202 if (_controller.isPaused) { | 180 if (_controller.isPaused) { |
| 203 if (_eventHandlerAdded) { | 181 var res = MojoHandleWatcher.remove(_handle); |
| 204 var res = MojoHandleWatcher.remove(_handle); | 182 if (!res.isOk) { |
| 205 if (!res.isOk) { | 183 throw "MojoHandleWatcher add failed: $res"; |
| 206 throw new Exception("MojoHandleWatcher add failed: $res"); | |
| 207 } | |
| 208 _eventHandlerAdded = false; | |
| 209 } | 184 } |
| 210 } else { | 185 } else { |
| 211 if (!_eventHandlerAdded) { | 186 var res = MojoHandleWatcher.add(_handle, _sendPort, _signals.value); |
| 212 var res = MojoHandleWatcher.add(_handle, _sendPort, _signals); | 187 if (!res.isOk) { |
| 213 if (!res.isOk) { | 188 throw "MojoHandleWatcher add failed: $res"; |
| 214 throw new Exception("MojoHandleWatcher add failed: $res"); | |
| 215 } | |
| 216 _eventHandlerAdded = true; | |
| 217 } | 189 } |
| 218 } | 190 } |
| 219 } | 191 } |
| 220 | 192 |
| 193 bool get readyRead => _handle.readyRead; | |
| 194 bool get readyWrite => _handle.readyWrite; | |
| 195 | |
| 221 String toString() => "$_handle"; | 196 String toString() => "$_handle"; |
| 222 } | 197 } |
| OLD | NEW |