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

Side by Side Diff: test/generated_sdk/lib/async/broadcast_stream_controller.dart

Issue 1162723007: remove generated_sdk from checked in code (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 months 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
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 part of dart.async;
6
7 class _BroadcastStream<T> extends _ControllerStream<T> {
8 _BroadcastStream(_StreamControllerLifecycle controller) : super(controller);
9
10 bool get isBroadcast => true;
11 }
12
13 abstract class _BroadcastSubscriptionLink {
14 _BroadcastSubscriptionLink _next;
15 _BroadcastSubscriptionLink _previous;
16 }
17
18 class _BroadcastSubscription<T> extends _ControllerSubscription<T>
19 implements _BroadcastSubscriptionLink {
20 static const int _STATE_EVENT_ID = 1;
21 static const int _STATE_FIRING = 2;
22 static const int _STATE_REMOVE_AFTER_FIRING = 4;
23 // TODO(lrn): Use the _state field on _ControllerSubscription to
24 // also store this state. Requires that the subscription implementation
25 // does not assume that it's use of the state integer is the only use.
26 int _eventState;
27
28 _BroadcastSubscriptionLink _next;
29 _BroadcastSubscriptionLink _previous;
30
31 _BroadcastSubscription(_StreamControllerLifecycle controller,
32 void onData(T data),
33 Function onError,
34 void onDone(),
35 bool cancelOnError)
36 : super(controller, onData, onError, onDone, cancelOnError) {
37 _next = _previous = this;
38 }
39
40 _BroadcastStreamController<T> get _controller => super._controller;
41
42 bool _expectsEvent(int eventId) =>
43 (_eventState & _STATE_EVENT_ID) == eventId;
44
45 void _toggleEventId() {
46 _eventState ^= _STATE_EVENT_ID;
47 }
48
49 bool get _isFiring => (_eventState & _STATE_FIRING) != 0;
50
51 void _setRemoveAfterFiring() {
52 assert(_isFiring);
53 _eventState |= _STATE_REMOVE_AFTER_FIRING;
54 }
55
56 bool get _removeAfterFiring =>
57 (_eventState & _STATE_REMOVE_AFTER_FIRING) != 0;
58
59 // The controller._recordPause doesn't do anything for a broadcast controller,
60 // so we don't bother calling it.
61 void _onPause() { }
62
63 // The controller._recordResume doesn't do anything for a broadcast
64 // controller, so we don't bother calling it.
65 void _onResume() { }
66
67 // _onCancel is inherited.
68 }
69
70
71 abstract class _BroadcastStreamController<T>
72 implements StreamController<T>,
73 _StreamControllerLifecycle<T>,
74 _BroadcastSubscriptionLink,
75 _EventSink<T>,
76 _EventDispatch<T> {
77 static const int _STATE_INITIAL = 0;
78 static const int _STATE_EVENT_ID = 1;
79 static const int _STATE_FIRING = 2;
80 static const int _STATE_CLOSED = 4;
81 static const int _STATE_ADDSTREAM = 8;
82
83 final _NotificationHandler _onListen;
84 final _NotificationHandler _onCancel;
85
86 // State of the controller.
87 int _state;
88
89 // Double-linked list of active listeners.
90 _BroadcastSubscriptionLink _next;
91 _BroadcastSubscriptionLink _previous;
92
93 // Extra state used during an [addStream] call.
94 _AddStreamState<T> _addStreamState;
95
96 /**
97 * Future returned by [close] and [done].
98 *
99 * The future is completed whenever the done event has been sent to all
100 * relevant listeners.
101 * The relevant listeners are the ones that were listening when [close] was
102 * called. When all of these have been canceled (sending the done event makes
103 * them cancel, but they can also be canceled before sending the event),
104 * this future completes.
105 *
106 * Any attempt to listen after calling [close] will throw, so there won't
107 * be any further listeners.
108 */
109 _Future _doneFuture;
110
111 _BroadcastStreamController(this._onListen, this._onCancel)
112 : _state = _STATE_INITIAL {
113 _next = _previous = this;
114 }
115
116 // StreamController interface.
117
118 Stream<T> get stream => new _BroadcastStream<T>(this);
119
120 StreamSink<T> get sink => new _StreamSinkWrapper<T>(this);
121
122 bool get isClosed => (_state & _STATE_CLOSED) != 0;
123
124 /**
125 * A broadcast controller is never paused.
126 *
127 * Each receiving stream may be paused individually, and they handle their
128 * own buffering.
129 */
130 bool get isPaused => false;
131
132 /** Whether there are currently one or more subscribers. */
133 bool get hasListener => !_isEmpty;
134
135 /**
136 * Test whether the stream has exactly one listener.
137 *
138 * Assumes that the stream has a listener (not [_isEmpty]).
139 */
140 bool get _hasOneListener {
141 assert(!_isEmpty);
142 return identical(_next._next, this);
143 }
144
145 /** Whether an event is being fired (sent to some, but not all, listeners). */
146 bool get _isFiring => (_state & _STATE_FIRING) != 0;
147
148 bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;
149
150 bool get _mayAddEvent => (_state < _STATE_CLOSED);
151
152 _Future _ensureDoneFuture() {
153 if (_doneFuture != null) return _doneFuture;
154 return _doneFuture = new _Future();
155 }
156
157 // Linked list helpers
158
159 bool get _isEmpty => identical(_next, this);
160
161 /** Adds subscription to linked list of active listeners. */
162 void _addListener(_BroadcastSubscription<T> subscription) {
163 assert(identical(subscription._next, subscription));
164 // Insert in linked list just before `this`.
165 subscription._previous = _previous;
166 subscription._next = this;
167 this._previous._next = subscription;
168 this._previous = subscription;
169 subscription._eventState = (_state & _STATE_EVENT_ID);
170 }
171
172 void _removeListener(_BroadcastSubscription<T> subscription) {
173 assert(identical(subscription._controller, this));
174 assert(!identical(subscription._next, subscription));
175 _BroadcastSubscriptionLink previous = subscription._previous;
176 _BroadcastSubscriptionLink next = subscription._next;
177 previous._next = next;
178 next._previous = previous;
179 subscription._next = subscription._previous = subscription;
180 }
181
182 // _StreamControllerLifecycle interface.
183
184 StreamSubscription<T> _subscribe(
185 void onData(T data),
186 Function onError,
187 void onDone(),
188 bool cancelOnError) {
189 if (isClosed) {
190 if (onDone == null) onDone = _nullDoneHandler;
191 return new _DoneStreamSubscription<T>(onDone);
192 }
193 StreamSubscription subscription =
194 new _BroadcastSubscription<T>(this, onData, onError, onDone,
195 cancelOnError);
196 _addListener(subscription);
197 if (identical(_next, _previous)) {
198 // Only one listener, so it must be the first listener.
199 _runGuarded(_onListen);
200 }
201 return subscription;
202 }
203
204 Future _recordCancel(StreamSubscription<T> subscription) {
205 // If already removed by the stream, don't remove it again.
206 if (identical(subscription._next, subscription)) return null;
207 assert(!identical(subscription._next, subscription));
208 if (subscription._isFiring) {
209 subscription._setRemoveAfterFiring();
210 } else {
211 assert(!identical(subscription._next, subscription));
212 _removeListener(subscription);
213 // If we are currently firing an event, the empty-check is performed at
214 // the end of the listener loop instead of here.
215 if (!_isFiring && _isEmpty) {
216 _callOnCancel();
217 }
218 }
219 return null;
220 }
221
222 void _recordPause(StreamSubscription<T> subscription) {}
223 void _recordResume(StreamSubscription<T> subscription) {}
224
225 // EventSink interface.
226
227 Error _addEventError() {
228 if (isClosed) {
229 return new StateError("Cannot add new events after calling close");
230 }
231 assert(_isAddingStream);
232 return new StateError("Cannot add new events while doing an addStream");
233 }
234
235 void add(T data) {
236 if (!_mayAddEvent) throw _addEventError();
237 _sendData(data);
238 }
239
240 void addError(Object error, [StackTrace stackTrace]) {
241 error = _nonNullError(error);
242 if (!_mayAddEvent) throw _addEventError();
243 AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
244 if (replacement != null) {
245 error = _nonNullError(replacement.error);
246 stackTrace = replacement.stackTrace;
247 }
248 _sendError(error, stackTrace);
249 }
250
251 Future close() {
252 if (isClosed) {
253 assert(_doneFuture != null);
254 return _doneFuture;
255 }
256 if (!_mayAddEvent) throw _addEventError();
257 _state |= _STATE_CLOSED;
258 Future doneFuture = _ensureDoneFuture();
259 _sendDone();
260 return doneFuture;
261 }
262
263 Future get done => _ensureDoneFuture();
264
265 Future addStream(Stream<T> stream, {bool cancelOnError: true}) {
266 if (!_mayAddEvent) throw _addEventError();
267 _state |= _STATE_ADDSTREAM;
268 _addStreamState = new _AddStreamState(this, stream, cancelOnError);
269 return _addStreamState.addStreamFuture;
270 }
271
272 // _EventSink interface, called from AddStreamState.
273 void _add(T data) {
274 _sendData(data);
275 }
276
277 void _addError(Object error, StackTrace stackTrace) {
278 _sendError(error, stackTrace);
279 }
280
281 void _close() {
282 assert(_isAddingStream);
283 _AddStreamState addState = _addStreamState;
284 _addStreamState = null;
285 _state &= ~_STATE_ADDSTREAM;
286 addState.complete();
287 }
288
289 // Event handling.
290 void _forEachListener(
291 void action(_BufferingStreamSubscription<T> subscription)) {
292 if (_isFiring) {
293 throw new StateError(
294 "Cannot fire new event. Controller is already firing an event");
295 }
296 if (_isEmpty) return;
297
298 // Get event id of this event.
299 int id = (_state & _STATE_EVENT_ID);
300 // Start firing (set the _STATE_FIRING bit). We don't do [_onCancel]
301 // callbacks while firing, and we prevent reentrancy of this function.
302 //
303 // Set [_state]'s event id to the next event's id.
304 // Any listeners added while firing this event will expect the next event,
305 // not this one, and won't get notified.
306 _state ^= _STATE_EVENT_ID | _STATE_FIRING;
307 _BroadcastSubscriptionLink link = _next;
308 while (!identical(link, this)) {
309 _BroadcastSubscription<T> subscription = link;
310 if (subscription._expectsEvent(id)) {
311 subscription._eventState |= _BroadcastSubscription._STATE_FIRING;
312 action(subscription);
313 subscription._toggleEventId();
314 link = subscription._next;
315 if (subscription._removeAfterFiring) {
316 _removeListener(subscription);
317 }
318 subscription._eventState &= ~_BroadcastSubscription._STATE_FIRING;
319 } else {
320 link = subscription._next;
321 }
322 }
323 _state &= ~_STATE_FIRING;
324
325 if (_isEmpty) {
326 _callOnCancel();
327 }
328 }
329
330 void _callOnCancel() {
331 assert(_isEmpty);
332 if (isClosed && _doneFuture._mayComplete) {
333 // When closed, _doneFuture is not null.
334 _doneFuture._asyncComplete(null);
335 }
336 _runGuarded(_onCancel);
337 }
338 }
339
340 class _SyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
341 _SyncBroadcastStreamController(void onListen(), void onCancel())
342 : super(onListen, onCancel);
343
344 // EventDispatch interface.
345
346 void _sendData(T data) {
347 if (_isEmpty) return;
348 if (_hasOneListener) {
349 _state |= _BroadcastStreamController._STATE_FIRING;
350 _BroadcastSubscription subscription = _next;
351 subscription._add(data);
352 _state &= ~_BroadcastStreamController._STATE_FIRING;
353 if (_isEmpty) {
354 _callOnCancel();
355 }
356 return;
357 }
358 _forEachListener((_BufferingStreamSubscription<T> subscription) {
359 subscription._add(data);
360 });
361 }
362
363 void _sendError(Object error, StackTrace stackTrace) {
364 if (_isEmpty) return;
365 _forEachListener((_BufferingStreamSubscription<T> subscription) {
366 subscription._addError(error, stackTrace);
367 });
368 }
369
370 void _sendDone() {
371 if (!_isEmpty) {
372 _forEachListener((_BroadcastSubscription<T> subscription) {
373 subscription._close();
374 });
375 } else {
376 assert(_doneFuture != null);
377 assert(_doneFuture._mayComplete);
378 _doneFuture._asyncComplete(null);
379 }
380 }
381 }
382
383 class _AsyncBroadcastStreamController<T> extends _BroadcastStreamController<T> {
384 _AsyncBroadcastStreamController(void onListen(), void onCancel())
385 : super(onListen, onCancel);
386
387 // EventDispatch interface.
388
389 void _sendData(T data) {
390 for (_BroadcastSubscriptionLink link = _next;
391 !identical(link, this);
392 link = link._next) {
393 _BroadcastSubscription<T> subscription = link;
394 subscription._addPending(new _DelayedData(data));
395 }
396 }
397
398 void _sendError(Object error, StackTrace stackTrace) {
399 for (_BroadcastSubscriptionLink link = _next;
400 !identical(link, this);
401 link = link._next) {
402 _BroadcastSubscription<T> subscription = link;
403 subscription._addPending(new _DelayedError(error, stackTrace));
404 }
405 }
406
407 void _sendDone() {
408 if (!_isEmpty) {
409 for (_BroadcastSubscriptionLink link = _next;
410 !identical(link, this);
411 link = link._next) {
412 _BroadcastSubscription<T> subscription = link;
413 subscription._addPending(const _DelayedDone());
414 }
415 } else {
416 assert(_doneFuture != null);
417 assert(_doneFuture._mayComplete);
418 _doneFuture._asyncComplete(null);
419 }
420 }
421 }
422
423 /**
424 * Stream controller that is used by [Stream.asBroadcastStream].
425 *
426 * This stream controller allows incoming events while it is firing
427 * other events. This is handled by delaying the events until the
428 * current event is done firing, and then fire the pending events.
429 *
430 * This class extends [_SyncBroadcastStreamController]. Events of
431 * an "asBroadcastStream" stream are always initiated by events
432 * on another stream, and it is fine to forward them synchronously.
433 */
434 class _AsBroadcastStreamController<T>
435 extends _SyncBroadcastStreamController<T>
436 implements _EventDispatch<T> {
437 _StreamImplEvents _pending;
438
439 _AsBroadcastStreamController(void onListen(), void onCancel())
440 : super(onListen, onCancel);
441
442 bool get _hasPending => _pending != null && ! _pending.isEmpty;
443
444 void _addPendingEvent(_DelayedEvent event) {
445 if (_pending == null) {
446 _pending = new _StreamImplEvents();
447 }
448 _pending.add(event);
449 }
450
451 void add(T data) {
452 if (!isClosed && _isFiring) {
453 _addPendingEvent(new _DelayedData<T>(data));
454 return;
455 }
456 super.add(data);
457 while (_hasPending) {
458 _pending.handleNext(this);
459 }
460 }
461
462 void addError(Object error, [StackTrace stackTrace]) {
463 if (!isClosed && _isFiring) {
464 _addPendingEvent(new _DelayedError(error, stackTrace));
465 return;
466 }
467 if (!_mayAddEvent) throw _addEventError();
468 _sendError(error, stackTrace);
469 while (_hasPending) {
470 _pending.handleNext(this);
471 }
472 }
473
474 Future close() {
475 if (!isClosed && _isFiring) {
476 _addPendingEvent(const _DelayedDone());
477 _state |= _BroadcastStreamController._STATE_CLOSED;
478 return super.done;
479 }
480 Future result = super.close();
481 assert(!_hasPending);
482 return result;
483 }
484
485 void _callOnCancel() {
486 if (_hasPending) {
487 _pending.clear();
488 _pending = null;
489 }
490 super._callOnCancel();
491 }
492 }
493
494 // A subscription that never receives any events.
495 // It can simulate pauses, but otherwise does nothing.
496 class _DoneSubscription<T> implements StreamSubscription<T> {
497 int _pauseCount = 0;
498 void onData(void handleData(T data)) {}
499 void onError(Function handleError) {}
500 void onDone(void handleDone()) {}
501 void pause([Future resumeSignal]) {
502 if (resumeSignal != null) resumeSignal.then(_resume);
503 _pauseCount++;
504 }
505 void resume() { _resume(null); }
506 void _resume(_) {
507 if (_pauseCount > 0) _pauseCount--;
508 }
509 Future cancel() { return new _Future.immediate(null); }
510 bool get isPaused => _pauseCount > 0;
511 Future asFuture([Object value]) => new _Future();
512 }
OLDNEW
« no previous file with comments | « test/generated_sdk/lib/async/async_error.dart ('k') | test/generated_sdk/lib/async/deferred_load.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698