Exemplo n.º 1
0
 internal void _cloneResult(_Future source)
 {
     D.assert(!_isComplete);
     D.assert(source._isComplete);
     _state             = source._state;
     _resultOrListeners = source._resultOrListeners;
 }
Exemplo n.º 2
0
        public static Future sync(Func <FutureOr> computation)
        {
            try {
                var result = computation();
                if (result.isFuture)
                {
                    return(result.f);
                }
                else
                {
                    return(_Future.value(result));
                }
            }
            catch (Exception error) {
                var        future      = new _Future();
                AsyncError replacement = Zone.current.errorCallback(error);
                if (replacement != null)
                {
                    future._asyncCompleteError(async_._nonNullError(replacement.InnerException));
                }
                else
                {
                    future._asyncCompleteError(error);
                }

                return(future);
            }
        }
Exemplo n.º 3
0
        static void _chainForeignFuture(Future source, _Future target)
        {
            D.assert(!target._isComplete);
            D.assert(!(source is _Future));

            // Mark the target as chained (and as such half-completed).
            target._setPendingComplete();
            try {
                source.then((value) => {
                    D.assert(target._isPendingComplete);
                    // The "value" may be another future if the foreign future
                    // implementation is mis-behaving,
                    // so use _complete instead of _completeWithValue.
                    target._clearPendingComplete();     // Clear this first, it's set again.
                    target._complete(FutureOr.value(value));
                    return(new FutureOr());
                },
                            onError: (Exception error) => {
                    D.assert(target._isPendingComplete);
                    target._completeError(error);
                    return(new FutureOr());
                });
            }
            catch (Exception e) {
                // This only happens if the `then` call threw synchronously when given
                // valid arguments.
                // That requires a non-conforming implementation of the Future interface,
                // which should, hopefully, never happen.
                async_.scheduleMicrotask(() => {
                    target._completeError(e);
                    return(null);
                });
            }
        }
Exemplo n.º 4
0
        internal static _Future immediateError(Exception error)
        {
            var future = new _Future(Zone.current);

            future._asyncCompleteError(error);
            return(future);
        }
Exemplo n.º 5
0
        Future <string> join(string separator = "")
        {
            _Future                result       = new _Future();
            StringBuilder          buffer       = new StringBuilder();
            StreamSubscription <T> subscription = null;
            bool first = true;

            subscription = listen(
                (T element) => {
                if (!first)
                {
                    buffer.Append(separator);
                }

                first = false;
                try {
                    buffer.Append(element);
                }
                catch (Exception e) {
                    _stream._cancelAndErrorWithReplacement(subscription, result, e);
                }
            },
                onError: (e, _) => result._completeError((Exception)e),
                onDone: () => { result._complete(buffer.ToString()); },
                cancelOnError: true);
            return(result.to <string>());
        }
Exemplo n.º 6
0
        internal static _Future zoneValue(object value, Zone zone)
        {
            var future = new _Future(zone);

            future._setValue(value);
            return(future);
        }
Exemplo n.º 7
0
        internal static _Future immediate(FutureOr result)
        {
            var future = new _Future(Zone.current);

            future._asyncComplete(result);
            return(future);
        }
Exemplo n.º 8
0
 public static _FutureListener whenComplete(_Future result, _FutureAction callback)
 {
     return(new _FutureListener(
                result, callback, null,
                stateWhencomplete
                ));
 }
Exemplo n.º 9
0
        internal void _addListener(_FutureListener listener)
        {
            D.assert(listener._nextListener == null);
            if (_mayAddListener)
            {
                listener._nextListener = (_FutureListener)_resultOrListeners;
                _resultOrListeners     = listener;
            }
            else
            {
                if (_isChained)
                {
                    // Delegate listeners to chained source future.
                    // If the source is complete, instead copy its values and
                    // drop the chaining.
                    _Future source = _chainSource;
                    if (!source._isComplete)
                    {
                        source._addListener(listener);
                        return;
                    }

                    _cloneResult(source);
                }

                D.assert(_isComplete);
                // Handle late listeners asynchronously.
                _zone.scheduleMicrotask(() => {
                    _propagateToListeners(this, listener);
                    return(null);
                });
            }
        }
Exemplo n.º 10
0
 _FutureListener(_Future result, Delegate callback, Func <Exception, FutureOr> errorCallback, int state)
 {
     this.result        = result;
     this.state         = state;
     this.callback      = callback;
     this.errorCallback = errorCallback;
 }
Exemplo n.º 11
0
 public static _FutureListener thenAwait(
     _Future result, _FutureOnValue onValue, Func <Exception, FutureOr> errorCallback)
 {
     return(new _FutureListener(
                result, onValue, errorCallback,
                ((errorCallback == null) ? stateThen : stateThenOnerror) | stateIsAwait
                ));
 }
Exemplo n.º 12
0
 public static _FutureListener catchError(_Future result, Func <Exception, FutureOr> errorCallback,
                                          _FutureErrorTest callback)
 {
     return(new _FutureListener(
                result, callback, errorCallback,
                (callback == null) ? stateCatcherror : stateCatcherrorTest
                ));
 }
Exemplo n.º 13
0
        internal static void _asyncCompleteWithErrorCallback(_Future result, Exception error)
        {
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error = _nonNullError(replacement.InnerException);
            }

            result._asyncCompleteError(error);
        }
Exemplo n.º 14
0
        public override Future timeout(TimeSpan timeLimit, Func <FutureOr> onTimeout = null)
        {
            if (_isComplete)
            {
                return(immediate(this));
            }

            _Future result = new _Future();
            Timer   timer;

            if (onTimeout == null)
            {
                timer = Timer.create(timeLimit, () => {
                    result._completeError(
                        new TimeoutException("Future not completed", timeLimit));
                    return(null);
                });
            }
            else
            {
                Zone zone = Zone.current;
                onTimeout = async_._registerHandler(onTimeout, zone);

                timer = Timer.create(timeLimit, () => {
                    try {
                        result._complete((FutureOr)zone.run(() => onTimeout()));
                    }
                    catch (Exception e) {
                        result._completeError(e);
                    }

                    return(null);
                });
            }

            then(v => {
                if (timer.isActive)
                {
                    timer.cancel();
                    result._completeWithValue(v);
                }

                return(FutureOr.nil);
            }, onError: e => {
                if (timer.isActive)
                {
                    timer.cancel();
                    result._completeError(e);
                }

                return(FutureOr.nil);
            });
            return(result);
        }
Exemplo n.º 15
0
        public Future forEach(Action <T> action)
        {
            _Future future = new _Future();
            StreamSubscription <T> subscription = null;

            subscription = listen(
                (T element) => {
                // TODO(floitsch): the type should be 'void' and inferred.
                _stream._runUserCode <object>(() => {
                    action(element);
                    return(default);
Exemplo n.º 16
0
        public override Future whenComplete(Func <FutureOr> action)
        {
            _Future result = new _Future();

            if (!ReferenceEquals(result._zone, async_._rootZone))
            {
                action = async_._registerHandler(action, result._zone);
            }

            _addListener(_FutureListener.whenComplete(result, action));
            return(result);
        }
Exemplo n.º 17
0
        internal static void _cancelAndErrorWithReplacement <T>(StreamSubscription <T> subscription,
                                                                _Future future, Exception error)
        {
            AsyncError replacement = Zone.current.errorCallback(error);

            if (replacement != null)
            {
                error = (Exception)_async._nonNullError(replacement);
            }

            _cancelAndError(subscription, future, error);
        }
Exemplo n.º 18
0
        static void _cancelAndError <T>(StreamSubscription <T> subscription, _Future future, Exception error
                                        )
        {
            var cancelFuture = subscription.cancel();

            if (cancelFuture != null && !Equals(cancelFuture, Future._nullFuture))
            {
                cancelFuture.whenComplete(() => future._completeError(error));
            }
            else
            {
                future._completeError(error);
            }
        }
Exemplo n.º 19
0
        public static Future microtask(Func <FutureOr> computation)
        {
            _Future result = new _Future();

            async_.scheduleMicrotask(() => {
                try {
                    result._complete(computation());
                }
                catch (Exception e) {
                    async_._completeWithErrorCallback(result, e);
                }

                return(null);
            });
            return(result);
        }
Exemplo n.º 20
0
        public override Future catchError(Func <Exception, FutureOr> onError, Func <Exception, bool> test = null)
        {
            _Future result = new _Future();

            if (!ReferenceEquals(result._zone, async_._rootZone))
            {
                onError = async_._registerErrorHandler(onError, result._zone);
                if (test != null)
                {
                    test = async_._registerUnaryHandler(test, result._zone);
                }
            }

            _addListener(_FutureListener.catchError(result, onError, test));
            return(result);
        }
Exemplo n.º 21
0
        Future <S> fold <S>(S initialValue, Func <S, T, S> combine)
        {
            _Future result = new _Future();
            S       value  = initialValue;
            StreamSubscription <T> subscription = null;

            subscription = listen(
                (T element) => {
                _stream._runUserCode(() => combine(value, element), (S newValue) => { value = newValue; },
                                     e => _stream._cancelAndErrorClosure(subscription, result)(e));
            },
                onError: (e, s) => result._completeError((Exception)e),
                onDone: () => { result._complete(FutureOr.value(value)); },
                cancelOnError: true);
            return(result.to <S>());
        }
Exemplo n.º 22
0
        public static Future create(Func <FutureOr> computation)
        {
            _Future result = new _Future();

            Timer.run(() => {
                try {
                    result._complete(computation());
                }
                catch (Exception e) {
                    async_._completeWithErrorCallback(result, e);
                }

                return(null);
            });
            return(result);
        }
Exemplo n.º 23
0
        public static Future doWhile(Func <FutureOr> action)
        {
            _Future           doneSignal    = new _Future();
            ZoneUnaryCallback nextIteration = null;

            // Bind this callback explicitly so that each iteration isn't bound in the
            // context of all the previous iterations' callbacks.
            // This avoids, e.g., deeply nested stack traces from the stack trace
            // package.
            nextIteration = Zone.current.bindUnaryCallbackGuarded((object keepGoingObj) => {
                bool keepGoing = (bool)keepGoingObj;
                while (keepGoing)
                {
                    FutureOr result;
                    try {
                        result = action();
                    }
                    catch (Exception error) {
                        // Cannot use _completeWithErrorCallback because it completes
                        // the future synchronously.
                        async_._asyncCompleteWithErrorCallback(doneSignal, error);
                        return(null);
                    }

                    if (result.isFuture)
                    {
                        result.f.then((value) => {
                            nextIteration((bool)value);
                            return(FutureOr.nil);
                        }, onError: error => {
                            doneSignal._completeError(error);
                            return(FutureOr.nil);
                        });
                        return(null);
                    }

                    keepGoing = (bool)result.v;
                }

                doneSignal._complete();
                return(null);
            });

            nextIteration(true);
            return(doneSignal);
        }
Exemplo n.º 24
0
        void _prependListeners(_FutureListener listeners)
        {
            if (listeners == null)
            {
                return;
            }
            if (_mayAddListener)
            {
                _FutureListener existingListeners = (_FutureListener)_resultOrListeners;
                _resultOrListeners = listeners;
                if (existingListeners != null)
                {
                    _FutureListener cursor = listeners;
                    while (cursor._nextListener != null)
                    {
                        cursor = cursor._nextListener;
                    }

                    cursor._nextListener = existingListeners;
                }
            }
            else
            {
                if (_isChained)
                {
                    // Delegate listeners to chained source future.
                    // If the source is complete, instead copy its values and
                    // drop the chaining.
                    _Future source = _chainSource;
                    if (!source._isComplete)
                    {
                        source._prependListeners(listeners);
                        return;
                    }

                    _cloneResult(source);
                }

                D.assert(_isComplete);
                listeners = _reverseListeners(listeners);
                _zone.scheduleMicrotask(() => {
                    _propagateToListeners(this, listeners);
                    return(null);
                });
            }
        }
Exemplo n.º 25
0
        public override Future then(Func <object, FutureOr> f, Func <Exception, FutureOr> onError = null)
        {
            Zone currentZone = Zone.current;

            if (!ReferenceEquals(currentZone, async_._rootZone))
            {
                f = async_._registerUnaryHandler(f, currentZone);
                if (onError != null)
                {
                    onError = async_._registerErrorHandler(onError, currentZone);
                }
            }

            _Future result = new _Future();

            _addListener(_FutureListener.then(result, f, onError));
            return(result);
        }
Exemplo n.º 26
0
        Future <bool> contains(object needle)
        {
            _Future future = new _Future();
            StreamSubscription <T> subscription = null;

            subscription = listen(
                (T element) => {
                _stream._runUserCode(() => (Equals(element, needle)), (bool isMatch) => {
                    if (isMatch)
                    {
                        _stream._cancelAndValue(subscription, future, true);
                    }
                }, (e) => _stream._cancelAndErrorClosure(subscription, future)(e));
            },
                onError: (e, _) => future._completeError((Exception)e),
                onDone: () => { future._complete(false); },
                cancelOnError: true);
            return(future.to <bool>());
        }
Exemplo n.º 27
0
        Future <T> reduce(Func <T, T, T> combine)
        {
            _Future result    = new _Future();
            bool    seenFirst = false;
            T       value     = default;
            StreamSubscription <T> subscription = null;

            subscription = listen(
                (T element) => {
                if (seenFirst)
                {
                    _stream._runUserCode(() => combine(value, element), (T newValue) => { value = newValue; },
                                         onError: (e) => _stream._cancelAndErrorClosure(subscription, result)(e));
                }
                else
                {
                    value     = element;
                    seenFirst = true;
                }
            },
                onError: (e, s) => result._completeError((Exception)e),
                onDone: () => {
                if (!seenFirst)
                {
                    try {
                        // Throw and recatch, instead of just doing
                        //  _completeWithErrorCallback, e, theError, StackTrace.current),
                        // to ensure that the stackTrace is set on the error.
                        throw new Exception("IterableElementError.noElement()");
                    }
                    catch (Exception e) {
                        async_._completeWithErrorCallback(result, e);
                    }
                }
                else
                {
                    // TODO: need check
                    result._complete(FutureOr.value(value));
                }
            },
                cancelOnError: true);
            return(result.to <T>());
        }
Exemplo n.º 28
0
        static void _chainCoreFuture(_Future source, _Future target)
        {
            D.assert(target._mayAddListener); // Not completed, not already chained.
            while (source._isChained)
            {
                source = source._chainSource;
            }

            if (source._isComplete)
            {
                _FutureListener listeners = target._removeListeners();
                target._cloneResult(source);
                _propagateToListeners(target, listeners);
            }
            else
            {
                _FutureListener listeners = (_FutureListener)target._resultOrListeners;
                target._setChained(source);
                source._prependListeners(listeners);
            }
        }
Exemplo n.º 29
0
        public static Future delayed(TimeSpan duration, Func <FutureOr> computation = null)
        {
            _Future result = new _Future();

            Timer.create(duration, () => {
                if (computation == null)
                {
                    result._complete();
                }
                else
                {
                    try {
                        result._complete(computation());
                    }
                    catch (Exception e) {
                        async_._completeWithErrorCallback(result, e);
                    }
                }

                return(null);
            });
            return(result);
        }
Exemplo n.º 30
0
        public static Future wait <T>(IEnumerable <Future> futures, bool eagerError = false, Action <T> cleanUp = null)
        {
            _Future   result    = new _Future();
            List <T>  values    = null; // Collects the values. Set to null on error.
            int       remaining = 0;    // How many futures are we waiting for.
            Exception error     = null; // The first error from a future.

            Func <Exception, FutureOr> handleError = (Exception theError) => {
                remaining--;
                if (values != null)
                {
                    if (cleanUp != null)
                    {
                        foreach (var value in values)
                        {
                            if (value != null)
                            {
                                // Ensure errors from cleanUp are uncaught.
                                sync(() => {
                                    cleanUp(value);
                                    return(FutureOr.nil);
                                });
                            }
                        }
                    }

                    values = null;
                    if (remaining == 0 || eagerError)
                    {
                        result._completeError(theError);
                    }
                    else
                    {
                        error = theError;
                    }
                }
                else if (remaining == 0 && !eagerError)
                {
                    result._completeError(error);
                }

                return(FutureOr.nil);
            };

            try {
                // As each future completes, put its value into the corresponding
                // position in the list of values.
                foreach (var future in futures)
                {
                    int pos = remaining;
                    future.then((object value) => {
                        remaining--;
                        if (values != null)
                        {
                            values[pos] = (T)value;
                            if (remaining == 0)
                            {
                                result._completeWithValue(values);
                            }
                        }
                        else
                        {
                            if (cleanUp != null && value != null)
                            {
                                // Ensure errors from cleanUp are uncaught.
                                sync(() => {
                                    cleanUp((T)value);
                                    return(FutureOr.nil);
                                });
                            }

                            if (remaining == 0 && !eagerError)
                            {
                                result._completeError(error);
                            }
                        }

                        return(FutureOr.nil);
                    }, onError: handleError);
                    // Increment the 'remaining' after the call to 'then'.
                    // If that call throws, we don't expect any future callback from
                    // the future, and we also don't increment remaining.
                    remaining++;
                }

                if (remaining == 0)
                {
                    return(value(FutureOr.value(new List <T>())));
                }

                values = new List <T>(new T[remaining]);
            }
            catch (Exception e) {
                // The error must have been thrown while iterating over the futures
                // list, or while installing a callback handler on the future.
                if (remaining == 0 || eagerError)
                {
                    // Throw a new Future.error.
                    // Don't just call `result._completeError` since that would propagate
                    // the error too eagerly, not giving the callers time to install
                    // error handlers.
                    // Also, don't use `_asyncCompleteError` since that one doesn't give
                    // zones the chance to intercept the error.
                    return(Future.error(e));
                }
                else
                {
                    // Don't allocate a list for values, thus indicating that there was an
                    // error.
                    // Set error to the caught exception.
                    error = e;
                }
            }

            return(result);
        }