OLD | NEW |
---|---|
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:stack_trace/stack_trace.dart'; | 10 import 'package:stack_trace/stack_trace.dart'; |
(...skipping 22 matching lines...) Expand all Loading... | |
33 /// The timeout timer. | 33 /// The timeout timer. |
34 /// | 34 /// |
35 /// If [_timeout] isn't null, this timer is set as soon as the resource limit | 35 /// If [_timeout] isn't null, this timer is set as soon as the resource limit |
36 /// is reached and is reset every time an resource is released or a new | 36 /// is reached and is reset every time an resource is released or a new |
37 /// resource is requested. If it fires, that indicates that the caller became | 37 /// resource is requested. If it fires, that indicates that the caller became |
38 /// deadlocked, likely due to files waiting for additional files to be read | 38 /// deadlocked, likely due to files waiting for additional files to be read |
39 /// before they could be closed. | 39 /// before they could be closed. |
40 Timer _timer; | 40 Timer _timer; |
41 | 41 |
42 /// The amount of time to wait before timing out the pending resources. | 42 /// The amount of time to wait before timing out the pending resources. |
43 Duration _timeout; | 43 final Duration _timeout; |
44 | 44 |
45 /// Creates a new pool with the given limit on how many resources may be | 45 /// Creates a new pool with the given limit on how many resources may be |
46 /// allocated at once. | 46 /// allocated at once. |
47 /// | 47 /// |
48 /// If [timeout] is passed, then if that much time passes without any activity | 48 /// If [timeout] is passed, then if that much time passes without any activity |
49 /// all pending [request] futures will throw an exception. This is indented | 49 /// all pending [request] futures will throw a [TimeoutException]. This is |
50 /// to avoid deadlocks. | 50 /// indented to avoid deadlocks. |
Alan Knight
2014/07/24 20:28:15
should be "intended"?
nweiz
2014/07/24 20:29:20
Yep!
| |
51 Pool(this._maxAllocatedResources, {Duration timeout}) | 51 Pool(this._maxAllocatedResources, {Duration timeout}) |
52 : _timeout = timeout; | 52 : _timeout = timeout; |
53 | 53 |
54 /// Request a [PoolResource]. | 54 /// Request a [PoolResource]. |
55 /// | 55 /// |
56 /// If the maximum number of resources is already allocated, this will delay | 56 /// If the maximum number of resources is already allocated, this will delay |
57 /// until one of them is released. | 57 /// until one of them is released. |
58 Future<PoolResource> request() { | 58 Future<PoolResource> request() { |
59 if (_allocatedResources < _maxAllocatedResources) { | 59 if (_allocatedResources < _maxAllocatedResources) { |
60 _allocatedResources++; | 60 _allocatedResources++; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 _timer = null; | 99 _timer = null; |
100 } else { | 100 } else { |
101 _timer = new Timer(_timeout, _onTimeout); | 101 _timer = new Timer(_timeout, _onTimeout); |
102 } | 102 } |
103 } | 103 } |
104 | 104 |
105 /// Handles [_timer] timing out by causing all pending resource completers to | 105 /// Handles [_timer] timing out by causing all pending resource completers to |
106 /// emit exceptions. | 106 /// emit exceptions. |
107 void _onTimeout() { | 107 void _onTimeout() { |
108 for (var completer in _requestedResources) { | 108 for (var completer in _requestedResources) { |
109 completer.completeError("Pool deadlock: all resources have been " | 109 completer.completeError( |
110 "allocated for too long.", new Chain.current()); | 110 new TimeoutException("Pool deadlock: all resources have been " |
111 "allocated for too long.", | |
112 _timeout), | |
113 new Chain.current()); | |
111 } | 114 } |
112 _requestedResources.clear(); | 115 _requestedResources.clear(); |
113 _timer = null; | 116 _timer = null; |
114 } | 117 } |
115 } | 118 } |
116 | 119 |
117 /// A member of a [Pool]. | 120 /// A member of a [Pool]. |
118 /// | 121 /// |
119 /// A [PoolResource] is a token that indicates that a resource is allocated. | 122 /// A [PoolResource] is a token that indicates that a resource is allocated. |
120 /// When the associated resource is released, the user should call [release]. | 123 /// When the associated resource is released, the user should call [release]. |
121 class PoolResource { | 124 class PoolResource { |
122 final Pool _pool; | 125 final Pool _pool; |
123 | 126 |
124 /// Whether [this] has been released yet. | 127 /// Whether [this] has been released yet. |
125 bool _released = false; | 128 bool _released = false; |
126 | 129 |
127 PoolResource._(this._pool); | 130 PoolResource._(this._pool); |
128 | 131 |
129 /// Tells the parent [Pool] that the resource associated with this resource is | 132 /// Tells the parent [Pool] that the resource associated with this resource is |
130 /// no longer allocated, and that a new [PoolResource] may be allocated. | 133 /// no longer allocated, and that a new [PoolResource] may be allocated. |
131 void release() { | 134 void release() { |
132 if (_released) { | 135 if (_released) { |
133 throw new StateError("A PoolResource may only be released once."); | 136 throw new StateError("A PoolResource may only be released once."); |
134 } | 137 } |
135 _released = true; | 138 _released = true; |
136 _pool._onResourceReleased(); | 139 _pool._onResourceReleased(); |
137 } | 140 } |
138 } | 141 } |
139 | 142 |
OLD | NEW |