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 |