Index: mojo/public/dart/system/lib/src/handle.dart |
diff --git a/mojo/public/dart/system/lib/src/handle.dart b/mojo/public/dart/system/lib/src/handle.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..115c968c29b31660d74a23eece8d68bd34f35ef5 |
--- /dev/null |
+++ b/mojo/public/dart/system/lib/src/handle.dart |
@@ -0,0 +1,153 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+part of core; |
+ |
+class _MojoHandleNatives { |
+ static int close(int handle) native "MojoHandle_Close"; |
+ static int wait(int handle, int signals, int deadline) |
+ native "MojoHandle_Wait"; |
+ static int waitMany( |
+ List handles, List signals, int num_handles, int deadline) |
+ native "MojoHandle_WaitMany"; |
+} |
+ |
+ |
+class RawMojoHandle { |
+ static final int INVALID = 0; |
+ static final int DEADLINE_INDEFINITE = -1; |
+ |
+ RawMojoHandle(this.h); |
+ |
+ int close() { |
+ int result = _MojoHandleNatives.close(h); |
+ h = INVALID; |
+ return result; |
+ } |
+ |
+ int wait(int signals, int deadline) { |
+ return _MojoHandleNatives.wait(h, signals, deadline); |
+ } |
+ |
+ bool _ready(int signal) { |
+ int res = wait(signal, 0); |
+ switch (res) { |
+ case MojoResult.OK: |
+ return true; |
+ case MojoResult.DEADLINE_EXCEEDED: |
+ case MojoResult.CANCELLED: |
+ case MojoResult.INVALID_ARGUMENT: |
+ case MojoResult.FAILED_PRECONDITION: |
+ return false; |
+ default: |
+ // Should be unreachable. |
+ throw new Exception("Unreachable"); |
+ } |
+ } |
+ |
+ bool readyRead() => _ready(MojoHandleSignals.READABLE); |
+ bool readyWrite() => _ready(MojoHandleSignals.WRITABLE); |
+ |
+ static int waitMany( |
+ List<int> handles, List signals, int deadline) { |
+ if (handles.length != signals.length) { |
+ return MojoResult.INVALID_ARGUMENT; |
+ } |
+ return _MojoHandleNatives.waitMany( |
+ handles, signals, handles.length, deadline); |
+ } |
+ |
+ static bool isValid(RawMojoHandle h) => (h.h != INVALID); |
+ |
+ int h; |
+} |
+ |
+ |
+class MojoHandle extends Stream<int> { |
+ RawMojoHandle _handle; |
+ StreamController _controller; |
+ SendPort _send_port; |
+ int _signals; |
+ bool _eventHandlerAdded; |
+ |
+ MojoHandle(this._handle) : |
+ _signals = MojoHandleSignals.READABLE, |
+ _eventHandlerAdded = false { |
+ ReceivePort rp = new ReceivePort(); |
+ _send_port = rp.sendPort; |
+ _controller = new StreamController(sync: true, |
+ onListen: _onSubscriptionStateChange, |
+ onCancel: _onSubscriptionStateChange, |
+ onPause: _onPauseStateChange, |
+ onResume: _onPauseStateChange); |
+ _controller.addStream(rp); |
+ } |
+ |
+ void close() { |
+ MojoHandleWatcher.close(_handle.h); |
+ _controller.close(); |
+ } |
+ |
+ _onDataClosure(origOnData) { |
+ return ((int event) { |
+ // The event handler removes this handle. |
+ _eventHandlerAdded = false; |
+ origOnData(event); |
+ int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
+ _eventHandlerAdded = true; |
+ if (res != MojoResult.OK) { |
+ throw new Exception("Failed to re-add handle: ${_handle.h}"); |
+ } |
+ }); |
+ } |
+ |
+ StreamSubscription<int> listen( |
+ void onData(int event), |
+ {Function onError, void onDone(), bool cancelOnError}) { |
+ |
+ int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
+ _eventHandlerAdded = true; |
+ if (res != MojoResult.OK) { |
+ throw new Exception("MojoHandleWatcher add failed: $res"); |
+ } |
+ |
+ return _controller.stream.listen( |
+ _onDataClosure(onData), |
+ onError: onError, |
+ onDone: onDone, |
+ cancelOnError: cancelOnError); |
+ } |
+ |
+ bool writeEnabled() => MojoHandleSignals.isWritable(_signals); |
+ |
+ void toggleWriteEvents() { |
+ //print("handle: ${_handle.h} toggle write"); |
+ _signals = MojoHandleSignals.toggleWrite(_signals); |
+ if (_eventHandlerAdded) { |
+ int res = MojoHandleWatcher.toggleWrite(_handle.h); |
+ if (res != MojoResult.OK) { |
+ throw new Exception("MojoHandleWatcher failed to toggle write: $res"); |
+ } |
+ } |
+ } |
+ |
+ void _onSubscriptionStateChange() { |
+ if (!_controller.hasListener) { |
+ close(); |
+ } |
+ } |
+ |
+ void _onPauseStateChange() { |
+ if (_controller.isPaused) { |
+ MojoHandleWatcher.remove(_handle.h); |
+ _eventHandlerAdded = false; |
+ } else { |
+ int res = MojoHandleWatcher.add(_handle.h, _send_port, _signals); |
+ if (res != MojoResult.OK) { |
+ throw new Exception("MojoHandleWatcher add failed: $res"); |
+ } |
+ _eventHandlerAdded = true; |
+ } |
+ } |
+} |