Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: lib/pool.dart

Issue 1415223004: Use the async package's new RestartableTimer class. (Closed) Base URL: git@github.com:dart-lang/pool@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library pool; 5 library pool;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'package:async/async.dart'; 10 import 'package:async/async.dart';
(...skipping 28 matching lines...) Expand all
39 final _onReleaseCompleters = new Queue<Completer<PoolResource>>(); 39 final _onReleaseCompleters = new Queue<Completer<PoolResource>>();
40 40
41 /// The maximum number of resources that may be allocated at once. 41 /// The maximum number of resources that may be allocated at once.
42 final int _maxAllocatedResources; 42 final int _maxAllocatedResources;
43 43
44 /// The number of resources that are currently allocated. 44 /// The number of resources that are currently allocated.
45 int _allocatedResources = 0; 45 int _allocatedResources = 0;
46 46
47 /// The timeout timer. 47 /// The timeout timer.
48 /// 48 ///
49 /// If [_timeout] isn't null, this timer is set as soon as the resource limit 49 /// This timer is canceled as long as the pool is below the resource limit.
50 /// is reached and is reset every time an resource is released or a new 50 /// It's reset once the resource limit is reached and again every time an
51 /// resource is requested. If it fires, that indicates that the caller became 51 /// resource is released or a new resource is requested. If it fires, that
52 /// deadlocked, likely due to files waiting for additional files to be read 52 /// indicates that the caller became deadlocked, likely due to files waiting
53 /// before they could be closed. 53 /// for additional files to be read before they could be closed.
54 Timer _timer; 54 ///
55 /// This is `null` if this pool shouldn't time out.
56 RestartableTimer _timer;
55 57
56 /// The amount of time to wait before timing out the pending resources. 58 /// The amount of time to wait before timing out the pending resources.
57 final Duration _timeout; 59 final Duration _timeout;
58 60
59 /// A [FutureGroup] that tracks all the `onRelease` callbacks for resources 61 /// A [FutureGroup] that tracks all the `onRelease` callbacks for resources
60 /// that have been marked releasable. 62 /// that have been marked releasable.
61 /// 63 ///
62 /// This is `null` until [close] is called. 64 /// This is `null` until [close] is called.
63 FutureGroup _closeGroup; 65 FutureGroup _closeGroup;
64 66
65 /// Whether [close] has been called. 67 /// Whether [close] has been called.
66 bool get isClosed => _closeGroup != null; 68 bool get isClosed => _closeGroup != null;
67 69
68 /// Creates a new pool with the given limit on how many resources may be 70 /// Creates a new pool with the given limit on how many resources may be
69 /// allocated at once. 71 /// allocated at once.
70 /// 72 ///
71 /// If [timeout] is passed, then if that much time passes without any activity 73 /// If [timeout] is passed, then if that much time passes without any activity
72 /// all pending [request] futures will throw a [TimeoutException]. This is 74 /// all pending [request] futures will throw a [TimeoutException]. This is
73 /// intended to avoid deadlocks. 75 /// intended to avoid deadlocks.
74 Pool(this._maxAllocatedResources, {Duration timeout}) 76 Pool(this._maxAllocatedResources, {Duration timeout})
75 : _timeout = timeout; 77 : _timeout = timeout {
78 if (timeout != null) {
79 // Start the timer canceled since we only want to start counting down once
80 // we've run out of available resources.
81 _timer = new RestartableTimer(timeout, _onTimeout)..cancel();
Bob Nystrom 2015/10/28 21:40:27 "cancel" is a weird name for this. To me, it impli
nweiz 2015/10/28 21:47:36 It's an inherited name from Timer. I wanted to kee
82 }
83 }
76 84
77 /// Request a [PoolResource]. 85 /// Request a [PoolResource].
78 /// 86 ///
79 /// If the maximum number of resources is already allocated, this will delay 87 /// If the maximum number of resources is already allocated, this will delay
80 /// until one of them is released. 88 /// until one of them is released.
81 Future<PoolResource> request() { 89 Future<PoolResource> request() {
82 if (isClosed) { 90 if (isClosed) {
83 throw new StateError("request() may not be called on a closed Pool."); 91 throw new StateError("request() may not be called on a closed Pool.");
84 } 92 }
85 93
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 _onReleaseCompleters.removeFirst().completeError(error, stackTrace); 191 _onReleaseCompleters.removeFirst().completeError(error, stackTrace);
184 }); 192 });
185 193
186 var completer = new Completer.sync(); 194 var completer = new Completer.sync();
187 _onReleaseCompleters.add(completer); 195 _onReleaseCompleters.add(completer);
188 return completer.future; 196 return completer.future;
189 } 197 }
190 198
191 /// A resource has been requested, allocated, or released. 199 /// A resource has been requested, allocated, or released.
192 void _resetTimer() { 200 void _resetTimer() {
193 if (_timer != null) _timer.cancel(); 201 if (_timer == null) return;
194 if (_timeout == null || _requestedResources.isEmpty) { 202
195 _timer = null; 203 if (_requestedResources.isEmpty) {
204 _timer.cancel();
196 } else { 205 } else {
197 _timer = new Timer(_timeout, _onTimeout); 206 _timer.reset();
198 } 207 }
199 } 208 }
200 209
201 /// Handles [_timer] timing out by causing all pending resource completers to 210 /// Handles [_timer] timing out by causing all pending resource completers to
202 /// emit exceptions. 211 /// emit exceptions.
203 void _onTimeout() { 212 void _onTimeout() {
204 for (var completer in _requestedResources) { 213 for (var completer in _requestedResources) {
205 completer.completeError( 214 completer.completeError(
206 new TimeoutException("Pool deadlock: all resources have been " 215 new TimeoutException("Pool deadlock: all resources have been "
207 "allocated for too long.", 216 "allocated for too long.",
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 /// produce additional information later on. For example, an isolate's task 257 /// produce additional information later on. For example, an isolate's task
249 /// may be complete, but it could still emit asynchronous errors. 258 /// may be complete, but it could still emit asynchronous errors.
250 void allowRelease(onRelease()) { 259 void allowRelease(onRelease()) {
251 if (_released) { 260 if (_released) {
252 throw new StateError("A PoolResource may only be released once."); 261 throw new StateError("A PoolResource may only be released once.");
253 } 262 }
254 _released = true; 263 _released = true;
255 _pool._onResourceReleaseAllowed(onRelease); 264 _pool._onResourceReleaseAllowed(onRelease);
256 } 265 }
257 } 266 }
OLDNEW
« no previous file with comments | « CHANGELOG.md ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698