Move pub/barback's Pool class into its own package.

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//399963004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@38525 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index deed1bc..6edf327 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.14.1+3
+
+* Add a dependency on the `pool` package.
+
 ## 0.14.1+2
 
 * Automatically log how long it takes long-running transforms to run.
diff --git a/lib/src/utils/file_pool.dart b/lib/src/utils/file_pool.dart
index 6bea4a4..6a23337 100644
--- a/lib/src/utils/file_pool.dart
+++ b/lib/src/utils/file_pool.dart
@@ -8,10 +8,10 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:pool/pool.dart';
 import 'package:stack_trace/stack_trace.dart';
 
 import '../utils.dart';
-import 'pool.dart';
 
 /// Manages a pool of files that are opened for reading to cope with maximum
 /// file descriptor limits.
diff --git a/lib/src/utils/pool.dart b/lib/src/utils/pool.dart
deleted file mode 100644
index c1c76bc..0000000
--- a/lib/src/utils/pool.dart
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library barback.utils.pool;
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:stack_trace/stack_trace.dart';
-
-import '../utils.dart';
-
-// TODO(nweiz): put this somewhere that it can be shared between packages.
-/// Manages an abstract pool of resources with a limit on how many may be in use
-/// at once.
-///
-/// When a resource is needed, the user should call [request]. When the returned
-/// future completes with a [PoolResource], the resource may be allocated. Once
-/// the resource has been released, the user should call [PoolResource.release].
-/// The pool will ensure that only a certain number of [PoolResource]s may be
-/// allocated at once.
-class Pool {
-  /// Completers for requests beyond the first [_maxAllocatedResources].
-  ///
-  /// When an item is released, the next element of [_requestedResources] will
-  /// be completed.
-  final _requestedResources = new Queue<Completer<PoolResource>>();
-
-  /// The maximum number of resources that may be allocated at once.
-  final int _maxAllocatedResources;
-
-  /// The number of resources that are currently allocated.
-  int _allocatedResources = 0;
-
-  /// The timeout timer.
-  ///
-  /// If [_timeout] isn't null, this timer is set as soon as the resource limit
-  /// is reached and is reset every time an resource is released or a new
-  /// resource is requested. If it fires, that indicates that the caller became
-  /// deadlocked, likely due to files waiting for additional files to be read
-  /// before they could be closed.
-  Timer _timer;
-
-  /// The amount of time to wait before timing out the pending resources.
-  Duration _timeout;
-
-  /// Creates a new pool with the given limit on how many resources may be
-  /// allocated at once.
-  ///
-  /// If [timeout] is passed, then if that much time passes without any activity
-  /// all pending [request] futures will throw an exception. This is indented
-  /// to avoid deadlocks.
-  Pool(this._maxAllocatedResources, {Duration timeout})
-      : _timeout = timeout;
-
-  /// Request a [PoolResource].
-  ///
-  /// If the maximum number of resources is already allocated, this will delay
-  /// until one of them is released.
-  Future<PoolResource> request() {
-    if (_allocatedResources < _maxAllocatedResources) {
-      _allocatedResources++;
-      return new Future.value(new PoolResource._(this));
-    } else {
-      var completer = new Completer<PoolResource>();
-      _requestedResources.add(completer);
-      _resetTimer();
-      return completer.future;
-    }
-  }
-
-  /// Requests a resource for the duration of [callback], which may return a
-  /// Future.
-  ///
-  /// The return value of [callback] is piped to the returned Future.
-  Future withResource(callback()) {
-    return request().then((resource) =>
-        syncFuture(callback).whenComplete(resource.release));
-  }
-
-  /// If there are any pending requests, this will fire the oldest one.
-  void _onResourceReleased() {
-    if (_requestedResources.isEmpty) {
-      _allocatedResources--;
-      if (_timer != null) {
-        _timer.cancel();
-        _timer = null;
-      }
-      return;
-    }
-
-    _resetTimer();
-    var pending = _requestedResources.removeFirst();
-    pending.complete(new PoolResource._(this));
-  }
-
-  /// A resource has been requested, allocated, or released.
-  void _resetTimer() {
-    if (_timer != null) _timer.cancel();
-    if (_timeout == null) {
-      _timer = null;
-    } else {
-      _timer = new Timer(_timeout, _onTimeout);
-    }
-  }
-
-  /// Handles [_timer] timing out by causing all pending resource completers to
-  /// emit exceptions.
-  void _onTimeout() {
-    for (var completer in _requestedResources) {
-      completer.completeError("Pool deadlock: all resources have been "
-          "allocated for too long.", new Chain.current());
-    }
-    _requestedResources.clear();
-    _timer = null;
-  }
-}
-
-/// A member of a [Pool].
-///
-/// A [PoolResource] is a token that indicates that a resource is allocated.
-/// When the associated resource is released, the user should call [release].
-class PoolResource {
-  final Pool _pool;
-
-  /// Whether [this] has been released yet.
-  bool _released = false;
-
-  PoolResource._(this._pool);
-
-  /// Tells the parent [Pool] that the resource associated with this resource is
-  /// no longer allocated, and that a new [PoolResource] may be allocated.
-  void release() {
-    if (_released) {
-      throw new StateError("A PoolResource may only be released once.");
-    }
-    _released = true;
-    _pool._onResourceReleased();
-  }
-}
diff --git a/pubspec.yaml b/pubspec.yaml
index cc7f5df..9d6fec3 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,7 +7,7 @@
 #
 # When the minor or patch version of this is upgraded, you *must* update that
 # version constraint in pub to stay in sync with this.
-version: 0.14.1+3
+version: 0.14.1+4
 
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
@@ -23,6 +23,7 @@
   responsiveness.
 dependencies:
   path: ">=0.9.0 <2.0.0"
+  pool: ">=1.0.0 <2.0.0"
   source_maps: ">=0.9.0 <0.10.0"
   stack_trace: ">=0.9.1 <2.0.0"
   collection: ">=0.9.1 <0.10.0"