OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 part of core; |
| 6 |
| 7 class _MojoHandleNatives { |
| 8 static int close(int handle) native "MojoHandle_Close"; |
| 9 static int wait(int handle, int signals, int deadline) |
| 10 native "MojoHandle_Wait"; |
| 11 static int waitMany( |
| 12 List handles, List signals, int num_handles, int deadline) |
| 13 native "MojoHandle_WaitMany"; |
| 14 } |
| 15 |
| 16 |
| 17 class RawMojoHandle { |
| 18 static final int INVALID = 0; |
| 19 static final int DEADLINE_INDEFINITE = -1; |
| 20 |
| 21 RawMojoHandle(this.h); |
| 22 |
| 23 int close() { |
| 24 int result = _MojoHandleNatives.close(h); |
| 25 h = INVALID; |
| 26 return result; |
| 27 } |
| 28 |
| 29 int wait(int signals, int deadline) { |
| 30 return _MojoHandleNatives.wait(h, signals, deadline); |
| 31 } |
| 32 |
| 33 bool _ready(int signal) { |
| 34 int res = wait(signal, 0); |
| 35 switch (res) { |
| 36 case MojoResult.OK: |
| 37 return true; |
| 38 case MojoResult.DEADLINE_EXCEEDED: |
| 39 case MojoResult.CANCELLED: |
| 40 case MojoResult.INVALID_ARGUMENT: |
| 41 case MojoResult.FAILED_PRECONDITION: |
| 42 return false; |
| 43 default: |
| 44 // Should be unreachable. |
| 45 throw new Exception("Unreachable"); |
| 46 } |
| 47 } |
| 48 |
| 49 bool readyRead() => _ready(MojoHandleSignals.READABLE); |
| 50 bool readyWrite() => _ready(MojoHandleSignals.WRITABLE); |
| 51 |
| 52 static int waitMany( |
| 53 List<int> handles, List signals, int deadline) { |
| 54 if (handles.length != signals.length) { |
| 55 return MojoResult.INVALID_ARGUMENT; |
| 56 } |
| 57 return _MojoHandleNatives.waitMany( |
| 58 handles, signals, handles.length, deadline); |
| 59 } |
| 60 |
| 61 static bool isValid(RawMojoHandle h) => (h.h != INVALID); |
| 62 |
| 63 int h; |
| 64 } |
| 65 |
| 66 |
| 67 class MojoHandle extends Stream<int> { |
| 68 RawMojoHandle _handle; |
| 69 StreamController _controller; |
| 70 SendPort _send_port; |
| 71 int _signals; |
| 72 bool _eventHandlerAdded; |
| 73 |
| 74 MojoHandle(this._handle) : |
| 75 _signals = MojoHandleSignals.READABLE, |
| 76 _eventHandlerAdded = false { |
| 77 ReceivePort rp = new ReceivePort(); |
| 78 _send_port = rp.sendPort; |
| 79 _controller = new StreamController(sync: true, |
| 80 onListen: _onSubscriptionStateChange, |
| 81 onCancel: _onSubscriptionStateChange, |
| 82 onPause: _onPauseStateChange, |
| 83 onResume: _onPauseStateChange); |
| 84 _controller.addStream(rp); |
| 85 } |
| 86 |
| 87 void close() { |
| 88 MojoHandleWatcher.close(_handle.h); |
| 89 _controller.close(); |
| 90 } |
| 91 |
| 92 _onDataClosure(origOnData) { |
| 93 return ((int event) { |
| 94 // The event handler removes this handle. |
| 95 _eventHandlerAdded = false; |
| 96 origOnData(event); |
| 97 int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
| 98 _eventHandlerAdded = true; |
| 99 if (res != MojoResult.OK) { |
| 100 throw new Exception("Failed to re-add handle: ${_handle.h}"); |
| 101 } |
| 102 }); |
| 103 } |
| 104 |
| 105 StreamSubscription<int> listen( |
| 106 void onData(int event), |
| 107 {Function onError, void onDone(), bool cancelOnError}) { |
| 108 |
| 109 int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
| 110 _eventHandlerAdded = true; |
| 111 if (res != MojoResult.OK) { |
| 112 throw new Exception("MojoHandleWatcher add failed: $res"); |
| 113 } |
| 114 |
| 115 return _controller.stream.listen( |
| 116 _onDataClosure(onData), |
| 117 onError: onError, |
| 118 onDone: onDone, |
| 119 cancelOnError: cancelOnError); |
| 120 } |
| 121 |
| 122 bool writeEnabled() => MojoHandleSignals.isWritable(_signals); |
| 123 |
| 124 void toggleWriteEvents() { |
| 125 //print("handle: ${_handle.h} toggle write"); |
| 126 _signals = MojoHandleSignals.toggleWrite(_signals); |
| 127 if (_eventHandlerAdded) { |
| 128 int res = MojoHandleWatcher.toggleWrite(_handle.h); |
| 129 if (res != MojoResult.OK) { |
| 130 throw new Exception("MojoHandleWatcher failed to toggle write: $res"); |
| 131 } |
| 132 } |
| 133 } |
| 134 |
| 135 void _onSubscriptionStateChange() { |
| 136 if (!_controller.hasListener) { |
| 137 close(); |
| 138 } |
| 139 } |
| 140 |
| 141 void _onPauseStateChange() { |
| 142 if (_controller.isPaused) { |
| 143 MojoHandleWatcher.remove(_handle.h); |
| 144 _eventHandlerAdded = false; |
| 145 } else { |
| 146 int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
| 147 if (res != MojoResult.OK) { |
| 148 throw new Exception("MojoHandleWatcher add failed: $res"); |
| 149 } |
| 150 _eventHandlerAdded = true; |
| 151 } |
| 152 } |
| 153 } |
OLD | NEW |