/// <summary>Immediately execute an async action on each element of an async sequence</summary>
        /// <typeparam name="TSource">Type of elements of the async sequence</typeparam>
        /// <param name="source">Source async sequence</param>
        /// <param name="mode">Expected execution mode of the query</param>
        /// <param name="action">Asynchronous action to perform on each element as it arrives</param>
        /// <param name="ct">Cancellation token that can be used to cancel the operation</param>
        /// <returns>Number of items that have been processed</returns>
        internal static async Task <long> Run <TSource>(
            [NotNull] IAsyncEnumerable <TSource> source,
            AsyncIterationHint mode,
            [NotNull] Func <TSource, Task> action,
            CancellationToken ct)
        {
            ct.ThrowIfCancellationRequested();

            //note: we should not use "ConfigureAwait(false)" here because we would like to execute the action in the original synchronization context if possible...

            long count = 0;

            using (var iterator = source.GetEnumerator(ct, mode))
            {
                Contract.Assert(iterator != null, "The underlying sequence returned a null async iterator");

                while (await iterator.MoveNextAsync())
                {
                    ct.ThrowIfCancellationRequested();
                    await action(iterator.Current);

                    ++count;
                }
            }
            return(count);
        }
        /// <summary>Immediately execute an action on each element of an async sequence, with the possibility of stopping before the end</summary>
        /// <typeparam name="TSource">Type of elements of the async sequence</typeparam>
        /// <param name="source">Source async sequence</param>
        /// <param name="mode">If different than default, can be used to optimise the way the source will produce the items</param>
        /// <param name="action">Lambda called for each element as it arrives. If the return value is true, the next value will be processed. If the return value is false, the iterations will stop immediately.</param>
        /// <param name="ct">Cancellation token that can be used to cancel the operation</param>
        /// <returns>Number of items that have been processed successfully</returns>
        internal static async Task <long> Run <TSource>(
            [NotNull] IAsyncEnumerable <TSource> source,
            AsyncIterationHint mode,
            [NotNull] Func <TSource, bool> action,
            CancellationToken ct)
        {
            Contract.NotNull(source, nameof(source));
            Contract.NotNull(action, nameof(action));

            ct.ThrowIfCancellationRequested();

            long count = 0;

            using (var iterator = source is IConfigurableAsyncEnumerable <TSource> configurable ? configurable.GetAsyncEnumerator(ct, mode) : source.GetAsyncEnumerator())
            {
                Contract.Assert(iterator != null, "The underlying sequence returned a null async iterator");

                while (await iterator.MoveNextAsync().ConfigureAwait(false))
                {
                    if (!action(iterator.Current))
                    {
                        break;
                    }
                    ++count;
                }
            }
            return(count);
        }
        public IAsyncEnumerator <TResult> GetEnumerator(CancellationToken ct, AsyncIterationHint mode)
        {
            ct.ThrowIfCancellationRequested();
            IAsyncEnumerator <TSource> inner = null;

            try
            {
                inner = this.Source.GetEnumerator(ct, mode);
                Contract.Requires(inner != null, "The underlying async sequence returned an empty enumerator");

                var outer = this.Factory(inner);
                if (outer == null)
                {
                    throw new InvalidOperationException("The async factory returned en empty enumerator");
                }

                return(outer);
            }
            catch (Exception)
            {
                //make sure that the inner iterator gets disposed if something went wrong
                inner?.Dispose();
                throw;
            }
        }
Exemple #4
0
        public IAsyncEnumerator <TResult> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint mode)
        {
            ct.ThrowIfCancellationRequested();
            IAsyncEnumerator <TSource>?inner = null;

            try
            {
                inner = this.Source is IConfigurableAsyncEnumerable <TSource> configurable?configurable.GetAsyncEnumerator(ct, mode) : this.Source.GetAsyncEnumerator(ct);

                Contract.Debug.Requires(inner != null, "The underlying async sequence returned an empty enumerator");

                var outer = this.Factory(inner);
                if (outer == null)
                {
                    throw new InvalidOperationException("The async factory returned en empty enumerator");
                }

                return(outer);
            }
            catch (Exception)
            {
                //make sure that the inner iterator gets disposed if something went wrong
                //BUGBUG: we have to block on the async disposable :(
                inner?.DisposeAsync().GetAwaiter().GetResult();
                throw;
            }
        }
Exemple #5
0
        /// <summary>Immediately execute an action on each element of an async sequence</summary>
        /// <typeparam name="TSource">Type of elements of the async sequence</typeparam>
        /// <param name="source">Source async sequence</param>
        /// <param name="mode">If different than default, can be used to optimise the way the source will produce the items</param>
        /// <param name="action">Action to perform on each element as it arrives</param>
        /// <param name="ct">Cancellation token that can be used to cancel the operation</param>
        /// <returns>Number of items that have been processed</returns>
        internal static async Task <long> Run <TSource>(
            IAsyncEnumerable <TSource> source,
            AsyncIterationHint mode,
            [InstantHandle] Action <TSource> action,
            CancellationToken ct)
        {
            Contract.NotNull(source);
            Contract.NotNull(action);

            ct.ThrowIfCancellationRequested();

            long count = 0;

            await using (var iterator = source is IConfigurableAsyncEnumerable <TSource> configurable ? configurable.GetAsyncEnumerator(ct, mode) : source.GetAsyncEnumerator(ct))
            {
                Contract.Debug.Assert(iterator != null, "The underlying sequence returned a null async iterator");

                while (await iterator.MoveNextAsync().ConfigureAwait(false))
                {
                    action(iterator.Current);
                    ++count;
                }
            }
            return(count);
        }
Exemple #6
0
            public IAsyncEnumerator <TSource> GetEnumerator(CancellationToken ct, AsyncIterationHint mode)
            {
                ct.ThrowIfCancellationRequested();
                var sorter     = GetEnumerableSorter(null);
                var enumerator = default(IAsyncEnumerator <TSource>);

                try
                {
                    enumerator = m_source.GetEnumerator(ct, mode);
                    return(new OrderedEnumerator <TSource>(enumerator, sorter, ct));
                }
                catch (Exception)
                {
                    enumerator?.Dispose();
                    throw;
                }
            }
Exemple #7
0
        public IAsyncEnumerator <TResult> GetEnumerator(CancellationToken ct, AsyncIterationHint mode)
        {
            ct.ThrowIfCancellationRequested();

            // reuse the same instance the first time
            if (Interlocked.CompareExchange(ref m_state, STATE_INIT, STATE_SEQ) == STATE_SEQ)
            {
                m_mode = mode;
                m_ct   = ct;
                return(this);
            }
            // create a new one
            var iter = Clone();

            iter.m_mode = mode;
            iter.m_ct   = ct;
            Volatile.Write(ref iter.m_state, STATE_INIT);
            return(iter);
        }
 public IAsyncEnumerator <T> GetEnumerator(CancellationToken ct, AsyncIterationHint _)
 {
     ct.ThrowIfCancellationRequested();
     return(m_factory(m_state, ct));
 }
        internal static IAsyncEnumerator <T> GetEnumerator([NotNull] FdbAsyncSequenceQuery <T> sequence, AsyncIterationHint mode)
        {
            var generator = sequence.CompileSequence(sequence.Expression);

            if (sequence.Transaction != null)
            {
                return(generator(sequence.Transaction).GetEnumerator(sequence.Transaction.Cancellation, mode));
            }

            //BUGBUG: how do we get a CancellationToken without a transaction?
            var ct = CancellationToken.None;

            IFdbTransaction      trans    = null;
            IAsyncEnumerator <T> iterator = null;
            bool success = true;

            try
            {
                trans    = sequence.Database.BeginTransaction(ct);
                iterator = generator(trans).GetEnumerator(ct, mode);

                return(new TransactionIterator(trans, iterator));
            }
            catch (Exception)
            {
                success = false;
                throw;
            }
            finally
            {
                if (!success)
                {
                    iterator?.Dispose();
                    trans?.Dispose();
                }
            }
        }
        internal static IAsyncEnumerator <T> GetEnumerator(FdbAsyncSequenceQuery <T> sequence, AsyncIterationHint mode)
        {
            var generator = sequence.CompileSequence(sequence.Expression);

            if (sequence.Transaction != null)
            {
                var source = generator(sequence.Transaction);
                Contract.Assert(source != null);
                return(source is IConfigurableAsyncEnumerable <T> configurable?configurable.GetAsyncEnumerator(sequence.Transaction.Cancellation, mode) : source.GetAsyncEnumerator(sequence.Transaction.Cancellation));
            }

            //BUGBUG: how do we get a CancellationToken without a transaction?
            var ct = CancellationToken.None;

            IFdbTransaction?     trans    = null;
            IAsyncEnumerator <T>?iterator = null;
            bool success = true;

            try
            {
#warning Fix async begin transaction!
                trans = sequence.Database !.BeginTransactionAsync(ct).GetAwaiter().GetResult();                //HACKHACK: BUGBUG: async!
                var source = generator(trans);
                Contract.Assert(source != null);
                iterator = source is IConfigurableAsyncEnumerable <T> configurable?configurable.GetAsyncEnumerator(ct, mode) : source.GetAsyncEnumerator(ct);

                return(new TransactionIterator(trans, iterator));
            }
            catch (Exception)
            {
                success = false;
                throw;
            }
            finally
            {
                if (!success)
                {
                    //BUGBUG: we have to block on the async disposable :(
                    iterator?.DisposeAsync().GetAwaiter().GetResult();
                    trans?.Dispose();
                }
            }
        }
 public IAsyncEnumerator <TElement> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint mode)
 {
     ct.ThrowIfCancellationRequested();
     return(new Enumerator(m_lambda, ct));
 }
            public IAsyncEnumerator <TSource> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint mode)
            {
                ct.ThrowIfCancellationRequested();
                var sorter     = GetEnumerableSorter(null);
                var enumerator = default(IAsyncEnumerator <TSource>);

                try
                {
                    enumerator = m_source is IConfigurableAsyncEnumerable <TSource> configurable?configurable.GetAsyncEnumerator(ct, mode) : m_source.GetAsyncEnumerator(ct);

                    return(new OrderedEnumerator <TSource>(enumerator, sorter, ct));
                }
                catch (Exception)
                {
                    //BUGBUG: we are forced to block on DisposeAsync() :(
                    enumerator?.DisposeAsync().GetAwaiter().GetResult();
                    throw;
                }
            }
 public IAsyncEnumerator <TSource> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint hint) => this;
Exemple #14
0
 public IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint hint)
 {
     return(new ResultIterator(this, this.Transaction, this.Transform).GetAsyncEnumerator(ct, hint));
 }
Exemple #15
0
 /// <summary>Return an async sequence that will return the results of this query</summary>
 public IAsyncEnumerable <T> ToEnumerable(AsyncIterationHint mode = AsyncIterationHint.Default)
 {
     return(AsyncEnumerable.Create((_, __) => GetEnumerator(this, mode)));
 }
Exemple #16
0
 public IAsyncEnumerator <TSource> GetEnumerator(CancellationToken ct, AsyncIterationHint mode)
 {
     ct.ThrowIfCancellationRequested();
     return(this);
 }
Exemple #17
0
            public IAsyncEnumerator <TResult> GetAsyncEnumerator(CancellationToken ct, AsyncIterationHint _)
            {
                IEnumerator <TSource>?inner = null;

                try
                {
                    inner = this.Source.GetEnumerator();
                    Contract.Assert(inner != null, "The underlying sequence returned an empty enumerator.");

                    var outer = this.Factory(inner, ct);
                    if (outer == null)
                    {
                        throw new InvalidOperationException("The async factory returned en empty enumerator.");
                    }

                    return(outer);
                }
                catch (Exception)
                {
                    //make sure that the inner iterator gets disposed if something went wrong
                    inner?.Dispose();
                    throw;
                }
            }