blob: 723de385d692486a7259a955a21244f524c1ea25 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// 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.
// part of dart.async;
/**
* A basic asynchronous notification.
*/
abstract class Signal {
factory Signal.delayed(int milliseconds) {
var completer = new SignalCompleter();
new Timer(milliseconds, (_) => completer.complete());
return completer.signal;
}
/**
* The [onComplete] handler is called when the signal completes.
*
* If the signal is already complete, the [onComplete] handler is called
* as soon as possible, but no sooner than the next time an event is fired.
*/
void then(void onComplete());
}
typedef _SignalCompleteHandler();
/**
* Simple [Signal] controller that creates a [Signal] and allows completing it.
*/
class SignalCompleter {
final Signal signal;
SignalCompleter() : signal = new _SignalImpl();
void complete() {
_SignalImpl mySignal = signal;
mySignal._complete();
}
}
/**
* Simple Signal implementation receiving its completion from a
* [SignalCompleter].
*/
class _SignalImpl implements Signal {
/** Single-linked list of "done" event handlers to notify. */
_SignalListener _listeners = null;
/** Whether the signal is already completed. */
bool _isComplete = false;
void then(void onComplete()) {
_listeners = new _SignalListener(_listeners, onComplete);
if (_isComplete) {
// Schedule the done events as soon as the event queue is ready.
new Timer(0, (Timer timer) { _sendDone(); });
}
}
/**
* Complete the signal.
*
* This immediately notifies all listeners on the signal.
*/
void _complete() {
assert(!_isComplete); // Only complete once.
_isComplete = true;
_sendDone();
}
/**
* Notify all listeners.
*/
void _sendDone() {
while (_listeners != null) {
_DoneHandler onDone = _listeners.listener;
_listeners = _listeners.next;
try {
onDone();
} catch (e, s) {
new AsyncError(e, s).throwDelayed();
}
}
}
}
/** Single-linked list element of the listeners on a [_SignalImpl]. */
class _SignalListener {
_SignalListener next;
_SignalCompleteHandler listener;
_SignalListener(this.next, this.listener);
}