| Index: packages/pool/lib/pool.dart
|
| diff --git a/packages/pool/lib/pool.dart b/packages/pool/lib/pool.dart
|
| index ef38614184badf457535678f6c00cc4e8f7fdc3b..04aaaea6590456dc4267dc1defe36bd6aea2015d 100644
|
| --- a/packages/pool/lib/pool.dart
|
| +++ b/packages/pool/lib/pool.dart
|
| @@ -2,8 +2,6 @@
|
| // 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 pool;
|
| -
|
| import 'dart:async';
|
| import 'dart:collection';
|
|
|
| @@ -65,7 +63,14 @@ class Pool {
|
| 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.
|
| @@ -108,15 +113,18 @@ class Pool {
|
| /// Future.
|
| ///
|
| /// The return value of [callback] is piped to the returned Future.
|
| - Future withResource(callback()) {
|
| + Future<T> withResource<T>(FutureOr<T> callback()) {
|
| if (isClosed) {
|
| throw new StateError(
|
| "withResource() may not be called on a closed Pool.");
|
| }
|
|
|
| - // TODO(nweiz): Use async/await when sdk#23497 is fixed.
|
| - return request().then((resource) {
|
| - return new Future.sync(callback).whenComplete(resource.release);
|
| + // We can't use async/await here because we need to start the request
|
| + // synchronously in case the pool is closed immediately afterwards. Async
|
| + // functions have an asynchronous gap between calling and running the body,
|
| + // and [close] could be called during that gap. See #3.
|
| + return request().then<Future<T>>((resource) {
|
| + return new Future<T>.sync(callback).whenComplete(resource.release);
|
| });
|
| }
|
|
|
| @@ -131,7 +139,7 @@ class Pool {
|
| /// 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();
|
| @@ -146,7 +154,8 @@ class Pool {
|
|
|
| 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() {
|
| @@ -191,7 +200,7 @@ class Pool {
|
| _onReleaseCompleters.removeFirst().completeError(error, stackTrace);
|
| });
|
|
|
| - var completer = new Completer.sync();
|
| + var completer = new Completer<PoolResource>.sync();
|
| _onReleaseCompleters.add(completer);
|
| return completer.future;
|
| }
|
|
|