Add a Pool.done getter. (#5)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 96d4c2f..66b4769 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.3.0
+
+* Add a `Pool.done` getter that returns the same future returned by
+  `Pool.close()`.
+
 ## 1.2.4
 
 * Fix a strong-mode error.
diff --git a/lib/pool.dart b/lib/pool.dart
index faa9f0e..67c4a82 100644
--- a/lib/pool.dart
+++ b/lib/pool.dart
@@ -63,7 +63,14 @@
   FutureGroup _closeGroup;
 
   /// Whether [close] has been called.
-  bool get isClosed => _closeGroup != null;
+  bool get isClosed => _closeMemo.hasRun;
+
+  /// A future that completes once the pool is closed and all its outstanding
+  /// resources have been released.
+  ///
+  /// If any [PoolResource.allowRelease] callback throws an exception after the
+  /// pool is closed, this completes with that exception.
+  Future get done => _closeMemo.future;
 
   /// Creates a new pool with the given limit on how many resources may be
   /// allocated at once.
@@ -132,7 +139,7 @@
   /// an error, the returned future completes with that error.
   ///
   /// This may be called more than once; it returns the same [Future] each time.
-  Future close() {
+  Future close() => _closeMemo.runOnce(() {
     if (_closeGroup != null) return _closeGroup.future;
 
     _resetTimer();
@@ -147,7 +154,8 @@
 
     if (_allocatedResources == 0) _closeGroup.close();
     return _closeGroup.future;
-  }
+  });
+  final _closeMemo = new AsyncMemoizer();
 
   /// If there are any pending requests, this will fire the oldest one.
   void _onResourceReleased() {
diff --git a/pubspec.yaml b/pubspec.yaml
index 145df2b..3029b9f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pool
-version: 1.2.4
+version: 1.3.0
 author: Dart Team <misc@dartlang.org>
 description: A class for managing a finite pool of resources.
 homepage: https://github.com/dart-lang/pool
diff --git a/test/pool_test.dart b/test/pool_test.dart
index bd44cb2..7fba9c0 100644
--- a/test/pool_test.dart
+++ b/test/pool_test.dart
@@ -279,6 +279,16 @@
     });
   });
 
+  test("done doesn't complete without close", () async {
+    var pool = new Pool(1);
+    pool.done.then(expectAsync1((_) {}, count: 0));
+
+    var resource = await pool.request();
+    resource.release();
+
+    await new Future.delayed(Duration.ZERO);
+  });
+
   group("close()", () {
     test("disallows request() and withResource()", () {
       var pool = new Pool(1)..close();
@@ -292,6 +302,7 @@
       expect(pool.request().then((resource2) {
         resource2.release();
       }), completes);
+      expect(pool.done, completes);
       expect(pool.close(), completes);
       resource1.release();
     });
@@ -405,6 +416,7 @@
       var completer = new Completer();
       resource.allowRelease(() => completer.future);
 
+      expect(pool.done, throwsA("oh no!"));
       expect(pool.close(), throwsA("oh no!"));
 
       await new Future.delayed(Duration.ZERO);