| Index: mojo/dart/packages/mojo/lib/src/event_subscription.dart
|
| diff --git a/mojo/dart/packages/mojo/lib/src/event_subscription.dart b/mojo/dart/packages/mojo/lib/src/event_subscription.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1e01f7ea9fa2e4c17fe2e484be0626134eae1e01
|
| --- /dev/null
|
| +++ b/mojo/dart/packages/mojo/lib/src/event_subscription.dart
|
| @@ -0,0 +1,129 @@
|
| +// 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 MojoEventSubscription {
|
| + // The underlying Mojo handle.
|
| + MojoHandle _handle;
|
| +
|
| + // The send port that we give to the handle watcher to notify us of handle
|
| + // events.
|
| + SendPort _sendPort;
|
| +
|
| + // The receive port on which we listen and receive events from the handle
|
| + // watcher.
|
| + RawReceivePort _receivePort;
|
| +
|
| + // The signals on this handle that we're interested in.
|
| + int _signals;
|
| +
|
| + // Whether subscribe() has been called.
|
| + bool _isSubscribed;
|
| +
|
| + MojoEventSubscription(MojoHandle handle,
|
| + [int signals = MojoHandleSignals.kPeerClosedReadable])
|
| + : _handle = handle,
|
| + _signals = signals,
|
| + _isSubscribed = false {
|
| + if (!MojoHandle.registerFinalizer(this)) {
|
| + throw new MojoInternalError("Failed to register the MojoHandle.");
|
| + }
|
| + }
|
| +
|
| + bool get readyRead => _handle.readyRead;
|
| + bool get readyWrite => _handle.readyWrite;
|
| + int get signals => _signals;
|
| +
|
| + Future close({bool immediate: false}) => _close(immediate: immediate);
|
| +
|
| + void subscribe(void handler(int event)) {
|
| + if (_isSubscribed) {
|
| + throw new MojoApiError("Already subscribed: $this.");
|
| + }
|
| + _receivePort = new RawReceivePort(handler);
|
| + _sendPort = _receivePort.sendPort;
|
| +
|
| + if (_signals != MojoHandleSignals.kNone) {
|
| + int res = MojoHandleWatcher.add(_handle.h, _sendPort, _signals);
|
| + if (res != MojoResult.kOk) {
|
| + throw new MojoInternalError("MojoHandleWatcher add failed: $res");
|
| + }
|
| + }
|
| + _isSubscribed = true;
|
| + }
|
| +
|
| + bool enableSignals([int signals]) {
|
| + if (signals != null) {
|
| + _signals = signals;
|
| + }
|
| + if (_isSubscribed) {
|
| + return MojoHandleWatcher.add(_handle.h, _sendPort, _signals) ==
|
| + MojoResult.kOk;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool enableReadEvents() =>
|
| + enableSignals(MojoHandleSignals.kPeerClosedReadable);
|
| + bool enableWriteEvents() => enableSignals(MojoHandleSignals.kWritable);
|
| + bool enableAllEvents() => enableSignals(MojoHandleSignals.kReadWrite);
|
| +
|
| + /// End the subscription by removing the handle from the handle watcher and
|
| + /// closing the Dart port, but do not close the underlying handle. The handle
|
| + /// can then be reused, or closed at a later time.
|
| + void unsubscribe({bool immediate: false}) {
|
| + if ((_handle == null) || !_isSubscribed || (_receivePort == null)) {
|
| + throw new MojoApiError("Cannont unsubscribe from a MojoEventSubscription "
|
| + "that has not been subscribed to");
|
| + }
|
| + MojoHandleWatcher.remove(_handle.h);
|
| + _receivePort.close();
|
| + _receivePort = null;
|
| + _sendPort = null;
|
| + _isSubscribed = false;
|
| + }
|
| +
|
| + @override
|
| + String toString() => "$_handle";
|
| +
|
| + Future _close({bool immediate: false, bool local: false}) {
|
| + if (_handle != null) {
|
| + if (_isSubscribed && !local) {
|
| + return _handleWatcherClose(immediate: immediate).then((result) {
|
| + // If the handle watcher is gone, then close the handle ourselves.
|
| + if (result != MojoResult.kOk) {
|
| + _localClose();
|
| + }
|
| + });
|
| + } else {
|
| + _localClose();
|
| + }
|
| + }
|
| + return new Future.value(null);
|
| + }
|
| +
|
| + Future _handleWatcherClose({bool immediate: false}) {
|
| + assert(_handle != null);
|
| + MojoHandleNatives.removeOpenHandle(_handle.h);
|
| + return MojoHandleWatcher.close(_handle.h, wait: !immediate).then((r) {
|
| + if (_receivePort != null) {
|
| + _receivePort.close();
|
| + _receivePort = null;
|
| + }
|
| + return r;
|
| + });
|
| + }
|
| +
|
| + void _localClose() {
|
| + if (_handle != null) {
|
| + _handle.close();
|
| + _handle = null;
|
| + }
|
| + if (_receivePort != null) {
|
| + _receivePort.close();
|
| + _receivePort = null;
|
| + }
|
| + }
|
| +}
|
|
|