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

Side by Side Diff: pkg/analyzer/lib/src/cancelable_future.dart

Issue 806733003: Make futures returned by AnalysisContext cancelable. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library cancelable_future;
6
7 import 'dart:async';
8
9 /**
10 * Type of callback called when the future returned by a CancelableCompleter
11 * is canceled.
12 */
13 typedef void CancelHandler();
14
15 class CancelableCompleter<T> implements Completer<T> {
Brian Wilkerson 2014/12/15 19:49:26 I'd like to see doc comments for all of the classe
Paul Berry 2014/12/16 16:58:06 Done.
16 /**
17 * The completer which holds the state of the computation. If the
18 * computation is canceled, this completer will remain in the non-completed
19 * state.
20 */
21 final Completer<T> _innerCompleter = new Completer<T>.sync();
22
23 /**
24 * The completer which holds the future that is exposed to the client
25 * through [future]. If the computation is canceled, this completer will
26 * be completed with a FutureCanceledError.
27 */
28 final Completer<T> _outerCompleter = new Completer<T>();
29
30 /**
31 * The callback to invoke if the 'cancel' method is called on the future
32 * returned by [future]. This callback will only be invoked if the future
33 * is canceled before being completed.
34 */
35 final CancelHandler _onCancel;
36
37 _CancelableCompleterFuture<T> _future;
38
39 /**
40 * Create a CancelableCompleter that will invoke the given callback
41 * synchronously if its future is canceled. The callback will not be
42 * invoked if the future is completed before being canceled.
Brian Wilkerson 2014/12/15 19:49:26 And the future will be completed with an error bef
43 */
44 CancelableCompleter(this._onCancel) {
45 _future = new _CancelableCompleterFuture<T>(this);
46
47 // When the client completes the inner completer, we need to check whether
48 // the outer completer has been completed. If it has, then the operation
49 // was canceled before it finished, and it's too late to un-cancel it, so
50 // we just ignore the result from the inner completer. If it hasn't, then
51 // we simply pass along the result from the inner completer to the outer
52 // completer.
53 //
54 // Note that the reason it is safe for the inner completer to be
55 // synchronous is that we don't expose its future to client code, and we
56 // only use it to complete the outer completer (which is asynchronous).
57 _innerCompleter.future.then((T value) {
58 if (!_outerCompleter.isCompleted) {
59 _outerCompleter.complete(value);
60 }
61 }, onError: (Object error, StackTrace stackTrace) {
62 if (!_outerCompleter.isCompleted) {
63 _outerCompleter.completeError(error, stackTrace);
64 }
65 });
66 }
67
68 @override
69 CancelableFuture<T> get future => _future;
70
71 @override
72 bool get isCompleted => _innerCompleter.isCompleted;
73
74 @override
75 void complete([value]) {
76 _innerCompleter.complete(value);
77 }
78
79 @override
80 void completeError(Object error, [StackTrace stackTrace]) {
81 _innerCompleter.completeError(error, stackTrace);
82 }
83
84 void _cancel() {
85 if (!_outerCompleter.isCompleted) {
86 _outerCompleter.completeError(new FutureCanceledError());
87 _onCancel();
88 }
89 }
90 }
91
92 /**
93 * An object representing a delayed computation that can be canceled.
94 */
95 abstract class CancelableFuture<T> implements Future<T> {
96 /**
97 * A CancelableFuture containing the result of calling [computation]
98 * asynchronously. Since the computation is started without delay, calling
99 * the future's cancel method will have no effect.
100 */
101 factory CancelableFuture(computation()) =>
102 new _WrappedFuture<T>(new Future<T>(computation));
103
104 /**
105 * A CancelableFuture containing the result of calling [computation] after
106 * [duration] has passed.
107 *
108 * TODO(paulberry): if the future is canceled before the duration has
109 * elapsed, the computation should not be performed.
110 */
111 factory CancelableFuture.delayed(Duration duration, [computation()]) =>
112 new _WrappedFuture<T>(new Future<T>.delayed(duration, computation));
113
114 /**
115 * A CancelableFuture that completes with error. Since the future is
116 * completed without delay, calling the future's cancel method will have no
117 * effect.
118 */
119 factory CancelableFuture.error(Object error, [StackTrace stackTrace]) =>
120 new _WrappedFuture<T>(new Future<T>.error(error, stackTrace));
121
122 /**
123 * A CancelableFuture containing the result of calling [computation]
124 * asynchronously with scheduleMicrotask. Since the computation is started
125 * without delay, calling the future's cancel method will have no effect.
126 */
127 factory CancelableFuture.microtask(computation()) =>
128 new _WrappedFuture<T>(new Future<T>.microtask(computation));
129
130 /**
131 * A CancelableFuture containing the result of immediately calling
132 * [computation]. Since the computation is started without delay, calling
133 * the future's cancel method will have no effect.
134 */
135 factory CancelableFuture.sync(computation()) =>
136 new _WrappedFuture<T>(new Future<T>.sync(computation));
137
138 /**
139 * A CancelableFuture whose value is available in the next event-loop
140 * iteration. Since the value is available without delay, calling the
141 * future's cancel method will have no effect.
142 */
143 factory CancelableFuture.value([value]) =>
144 new _WrappedFuture<T>(new Future<T>.value(value));
145
146 /**
147 * If the delayed computation has not yet completed, attempt to cancel it.
148 * Note that the cancellation is not always possible. If the computation
149 * could be canceled, the future is completed with a FutureCanceledError.
150 * Otherwise it will behave as though cancel() was not called.
151 *
152 * Note that attempting to cancel a future that has already completed will
153 * never succeed--futures that have already completed retain their final
154 * state forever.
155 */
156 void cancel();
157 }
158
159 class FutureCanceledError {
160 }
161
162 class _CancelableCompleterFuture<T> implements CancelableFuture<T> {
163 final CancelableCompleter<T> _completer;
164
165 _CancelableCompleterFuture(this._completer);
166
167 @override
168 Stream<T> asStream() {
169 // TODO(paulberry): Implement this in such a way that
170 // StreamSubscription.cancel() cancels the future.
171 return _completer._outerCompleter.future.asStream();
172 }
173
174 @override
175 void cancel() {
176 _completer._cancel();
177 }
178
179 @override
180 Future catchError(Function onError, {bool test(Object error)}) =>
181 _completer._outerCompleter.future.catchError(onError, test: test);
182
183 @override
184 Future then(onValue(T value), {Function onError}) =>
185 _completer._outerCompleter.future.then(onValue, onError: onError);
186
187 @override
188 Future timeout(Duration timeLimit, {onTimeout()}) {
189 // TODO(paulberry): Implement this in such a way that a timeout cancels
190 // the future.
191 return _completer._outerCompleter.future.timeout(
192 timeLimit,
193 onTimeout: onTimeout);
194 }
195
196 @override
197 Future<T> whenComplete(action()) =>
198 _completer._outerCompleter.future.whenComplete(action);
199 }
200
201 /**
202 * A CancelableFuture that wraps an ordinary Future. Attempting to cancel a
203 * _WrappedFuture has no effect.
204 */
205 class _WrappedFuture<T> implements CancelableFuture<T> {
206 final Future<T> _future;
207
208 _WrappedFuture(this._future);
209
210 @override
211 Stream asStream() => _future.asStream();
212
213 @override
214 void cancel() {}
215
216 @override
217 Future catchError(Function onError, {bool test(Object error)}) =>
218 _future.catchError(onError, test: test);
219
220 @override
221 Future then(onValue(value), {Function onError}) =>
222 _future.then(onValue, onError: onError);
223
224 @override
225 Future timeout(Duration timeLimit, {onTimeout()}) =>
226 _future.timeout(timeLimit, onTimeout: onTimeout);
227
228 @override
229 Future whenComplete(action()) => _future.whenComplete(action);
230 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/engine.dart » ('j') | pkg/analyzer/test/generated/engine_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698