Пример #1
0
            public override async ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken)
            {
                CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                if (_connection == null || buffer.Length == 0)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                Debug.Assert(_contentBytesRemaining > 0);

                if ((ulong)buffer.Length > _contentBytesRemaining)
                {
                    buffer = buffer.Slice(0, (int)_contentBytesRemaining);
                }

                ValueTask <int> readTask = _connection.ReadAsync(buffer);
                int             bytesRead;

                if (readTask.IsCompletedSuccessfully)
                {
                    bytesRead = readTask.Result;
                }
                else
                {
                    CancellationTokenRegistration ctr = _connection.RegisterCancellation(cancellationToken);
                    try
                    {
                        bytesRead = await readTask.ConfigureAwait(false);
                    }
                    catch (Exception exc) when(CancellationHelper.ShouldWrapInOperationCanceledException(exc, cancellationToken))
                    {
                        throw CancellationHelper.CreateOperationCanceledException(exc, cancellationToken);
                    }
                    finally
                    {
                        ctr.Dispose();
                    }
                }

                if (bytesRead <= 0)
                {
                    // A cancellation request may have caused the EOF.
                    CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

                    // Unexpected end of response stream.
                    throw new IOException(SR.Format(SR.net_http_invalid_response_premature_eof_bytecount, _contentBytesRemaining));
                }

                Debug.Assert((ulong)bytesRead <= _contentBytesRemaining);
                _contentBytesRemaining -= (ulong)bytesRead;

                if (_contentBytesRemaining == 0)
                {
                    // End of response body
                    if (HttpTelemetry.Log.IsEnabled())
                    {
                        LogRequestStop();
                    }
                    _connection.CompleteResponse();
                    _connection = null;
                }

                return(bytesRead);
            }
Пример #2
0
 /// <summary>
 /// Make a task execute synchronously
 /// </summary>
 /// <param name="task">Task</param>
 public static void Sync(this ValueTask task)
 {
     task.ConfigureAwait(false).GetAwaiter().GetResult();
 }
            static async Task <TiffInkSet> TransformValueTaskAsync(ValueTask <TiffValueCollection <ushort> > valueTask)
            {
                TiffValueCollection <ushort> result = await valueTask.ConfigureAwait(false);

                return(result.IsEmpty ? TiffInkSet.CMYK : (TiffInkSet)result.GetFirstOrDefault());
            }
 async ValueTask ConditionalExpression(int x, ValueTask <int> vt)
 {
     return(x > 3 ? await vt : await vt.ConfigureAwait(false));
 }
Пример #5
0
 public static ConfiguredValueTaskAwaitable <T> Ignore <T>(this ValueTask <T> task) => task.ConfigureAwait(false);
Пример #6
0
        public async Task Reader_ContinuesOnCurrentTaskSchedulerIfDesired(
            bool readOrWait, bool completeBeforeOnCompleted, bool flowExecutionContext, bool?continueOnCapturedContext)
        {
            if (AllowSynchronousContinuations)
            {
                return;
            }

            await Task.Run(async() =>
            {
                Assert.Null(SynchronizationContext.Current);

                Channel <bool> c    = CreateChannel <bool>();
                ValueTask <bool> vt = readOrWait ?
                                      c.Reader.ReadAsync() :
                                      c.Reader.WaitToReadAsync();

                var continuationRan            = new TaskCompletionSource <bool>();
                var asyncLocal                 = new AsyncLocal <int>();
                bool schedulerWasFlowed        = false;
                bool executionContextWasFlowed = false;
                Action continuation            = () =>
                {
                    schedulerWasFlowed        = TaskScheduler.Current is CustomTaskScheduler;
                    executionContextWasFlowed = 42 == asyncLocal.Value;
                    continuationRan.SetResult(true);
                };

                if (completeBeforeOnCompleted)
                {
                    Assert.False(vt.IsCompleted);
                    Assert.False(vt.IsCompletedSuccessfully);
                    c.Writer.TryWrite(true);
                }

                await Task.Factory.StartNew(() =>
                {
                    Assert.IsType <CustomTaskScheduler>(TaskScheduler.Current);
                    asyncLocal.Value = 42;
                    switch (continueOnCapturedContext)
                    {
                    case null:
                        if (flowExecutionContext)
                        {
                            vt.GetAwaiter().OnCompleted(continuation);
                        }
                        else
                        {
                            vt.GetAwaiter().UnsafeOnCompleted(continuation);
                        }
                        break;

                    default:
                        if (flowExecutionContext)
                        {
                            vt.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().OnCompleted(continuation);
                        }
                        else
                        {
                            vt.ConfigureAwait(continueOnCapturedContext.Value).GetAwaiter().UnsafeOnCompleted(continuation);
                        }
                        break;
                    }
                    asyncLocal.Value = 0;
                }, CancellationToken.None, TaskCreationOptions.None, new CustomTaskScheduler());

                if (!completeBeforeOnCompleted)
                {
                    Assert.False(vt.IsCompleted);
                    Assert.False(vt.IsCompletedSuccessfully);
                    c.Writer.TryWrite(true);
                }

                await continuationRan.Task;
                Assert.True(vt.IsCompleted);
                Assert.True(vt.IsCompletedSuccessfully);

                Assert.Equal(continueOnCapturedContext != false, schedulerWasFlowed);
                if (completeBeforeOnCompleted) // OnCompleted will simply queue using a mechanism that happens to flow
                {
                    Assert.True(executionContextWasFlowed);
                }
                else
                {
                    Assert.Equal(flowExecutionContext, executionContextWasFlowed);
                }
            });
        }
Пример #7
0
 public static async ValueTask <ISourceStream> AwaitValueTaskSourceStreamGeneric <T>(
     ValueTask <ISourceStream <T> > task)
 {
     return(await task.ConfigureAwait(false));
 }
Пример #8
0
        private static async Task WriteMessageCore(ValueTask writeMessageTask)
        {
            await writeMessageTask.ConfigureAwait(false);

            GrpcEventSource.Log.MessageSent();
        }
Пример #9
0
            static async IAsyncEnumerable <TSource> Core(IAsyncEnumerable <TSource>[] sources, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default)
#if USE_FAIR_AND_CHEAPER_MERGE
            //
            // This new implementation of Merge differs from the original one in a few ways:
            //
            // - It's cheaper because:
            //   - no conversion from ValueTask<bool> to Task<bool> takes place using AsTask,
            //   - we don't instantiate Task.WhenAny tasks for each iteration.
            // - It's fairer because:
            //   - the MoveNextAsync tasks are awaited concurently, but completions are queued,
            //     instead of awaiting a new WhenAny task where "left" sources have preferential
            //     treatment over "right" sources.
            //
            {
                var count = sources.Length;

                var enumerators   = new IAsyncEnumerator <TSource> [count];
                var moveNextTasks = new ValueTask <bool> [count];

                try
                {
                    for (var i = 0; i < count; i++)
                    {
                        IAsyncEnumerator <TSource> enumerator = sources[i].GetAsyncEnumerator(cancellationToken);
                        enumerators[i] = enumerator;

                        // REVIEW: This follows the lead of the original implementation where we kick off MoveNextAsync
                        //         operations immediately. An alternative would be to do this in a separate stage, thus
                        //         preventing concurrency across MoveNextAsync and GetAsyncEnumerator calls and avoiding
                        //         any MoveNextAsync calls before all enumerators are acquired (or an exception has
                        //         occurred doing so).

                        moveNextTasks[i] = enumerator.MoveNextAsync();
                    }

                    var whenAny = TaskExt.WhenAny(moveNextTasks);

                    int active = count;

                    while (active > 0)
                    {
                        int index = await whenAny;

                        IAsyncEnumerator <TSource> enumerator   = enumerators[index];
                        ValueTask <bool>           moveNextTask = moveNextTasks[index];

                        if (!await moveNextTask.ConfigureAwait(false))
                        {
                            //
                            // Replace the task in our array by a completed task to make finally logic easier. Note that
                            // the WhenAnyValueTask object has a reference to our array (i.e. no copy is made), so this
                            // gets rid of any resources the original task may have held onto. However, we *don't* call
                            // whenAny.Replace to set this value, because it'd attach an awaiter to the already completed
                            // task, causing spurious wake-ups when awaiting whenAny.
                            //

                            moveNextTasks[index] = new ValueTask <bool>();

                            // REVIEW: The original implementation did not dispose eagerly, which could lead to resource
                            //         leaks when merged with other long-running sequences.

                            enumerators[index] = null; // NB: Avoids attempt at double dispose in finally if disposing fails.
                            await enumerator.DisposeAsync().ConfigureAwait(false);

                            active--;
                        }
                        else
                        {
                            TSource item = enumerator.Current;

                            //
                            // Replace the task using whenAny.Replace, which will write it to the moveNextTasks array, and
                            // will start awaiting the task. Note we don't have to write to moveNextTasks ourselves because
                            // the whenAny object has a reference to it (i.e. no copy is made).
                            //

                            whenAny.Replace(index, enumerator.MoveNextAsync());

                            yield return(item);
                        }
                    }
                }
                finally
                {
                    // REVIEW: The original implementation performs a concurrent dispose, which seems undesirable given the
                    //         additional uncontrollable source of concurrency and the sequential resource acquisition. In
                    //         this modern implementation, we release resources in opposite order as we acquired them, thus
                    //         guaranteeing determinism (and mimicking a series of nested `await using` statements).

                    // REVIEW: If we decide to phase GetAsyncEnumerator and the initial MoveNextAsync calls at the start of
                    //         the operator implementation, we should make this symmetric and first await all in flight
                    //         MoveNextAsync operations, prior to disposing the enumerators.

                    var errors = default(List <Exception>);

                    for (var i = count - 1; i >= 0; i--)
                    {
                        ValueTask <bool>           moveNextTask = moveNextTasks[i];
                        IAsyncEnumerator <TSource> enumerator   = enumerators[i];

                        try
                        {
                            try
                            {
                                //
                                // Await the task to ensure outstanding work is completed prior to performing a dispose
                                // operation. Note that we don't have to do anything special for tasks belonging to
                                // enumerators that have finished; we swapped in a placeholder completed task.
                                //

                                // REVIEW: This adds an additional continuation to all of the pending tasks (note that
                                //         whenAny also has registered one). The whenAny object will be collectible
                                //         after all of these complete. Alternatively, we could drain via whenAny, by
                                //         awaiting it until the active count drops to 0. This saves on attaching the
                                //         additional continuations, but we need to decide on order of dispose. Right
                                //         now, we dispose in opposite order of acquiring the enumerators, with the
                                //         exception of enumerators that were disposed eagerly upon early completion.
                                //         Should we care about the dispose order at all?

                                _ = await moveNextTask.ConfigureAwait(false);
                            }
                            finally
                            {
                                if (enumerator != null)
                                {
                                    await enumerator.DisposeAsync().ConfigureAwait(false);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            if (errors == null)
                            {
                                errors = new List <Exception>();
                            }

                            errors.Add(ex);
                        }
                    }

                    // NB: If we had any errors during cleaning (and awaiting pending operations), we throw these exceptions
                    //     instead of the original exception that may have led to running the finally block. This is similar
                    //     to throwing from any finally block (except that we catch all exceptions to ensure cleanup of all
                    //     concurrent sequences being merged).

                    if (errors != null)
                    {
                        throw new AggregateException(errors);
                    }
                }
            }
Пример #10
0
 private static async ValueTask <IAsyncDbTransaction> WrapValue <TTransaction>(ValueTask <TTransaction> transaction)
     where TTransaction : IDbTransaction
 {
     return(Create(await transaction.ConfigureAwait(Common.Configuration.ContinueOnCapturedContext)));
 }
Пример #11
0
 public async Task ConfiguredAwaiter_ContinuesOnCapturedContext(bool continueOnCapturedContext)
 {
     await Task.Run(() =>
     {
         var tsc = new TrackingSynchronizationContext();
         SynchronizationContext.SetSynchronizationContext(tsc);
         try
         {
             ValueTask<int> t = new ValueTask<int>(42);
             var mres = new ManualResetEventSlim();
             t.ConfigureAwait(continueOnCapturedContext).GetAwaiter().OnCompleted(() => mres.Set());
             Assert.True(mres.Wait(10000));
             Assert.Equal(continueOnCapturedContext ? 1 : 0, tsc.Posts);
         }
         finally
         {
             SynchronizationContext.SetSynchronizationContext(null);
         }
     });
 }
Пример #12
0
        public async Task ConfiguredAwaiter_OnCompleted(bool continueOnCapturedContext)
        {
            // Since ValueTask implements both OnCompleted and UnsafeOnCompleted,
            // OnCompleted typically won't be used by await, so we add an explicit test
            // for it here.

            ValueTask<int> t = new ValueTask<int>(42);
            var tcs = new TaskCompletionSource<bool>();
            t.ConfigureAwait(continueOnCapturedContext).GetAwaiter().OnCompleted(() => tcs.SetResult(true));
            await tcs.Task;
        }
Пример #13
0
        private async ValueTask <int> FinishReadAsyncMemory(
            ValueTask <int> readTask, Memory <byte> buffer, CancellationToken cancellationToken)
        {
            try
            {
                Debug.Assert(_inflater != null && _buffer != null);
                while (true)
                {
                    if (_inflater.NeedsInput())
                    {
                        int bytesRead = await readTask.ConfigureAwait(false);

                        EnsureNotDisposed();

                        if (bytesRead <= 0)
                        {
                            // This indicates the base stream has received EOF
                            return(0);
                        }
                        else if (bytesRead > _buffer.Length)
                        {
                            // The stream is either malicious or poorly implemented and returned a number of
                            // bytes larger than the buffer supplied to it.
                            throw new InvalidDataException(SR.GenericInvalidData);
                        }

                        cancellationToken.ThrowIfCancellationRequested();

                        // Feed the data from base stream into decompression engine
                        _inflater.SetInput(_buffer, 0, bytesRead);
                    }

                    // Finish inflating any bytes in the input buffer
                    int inflatedBytes = 0, bytesReadIteration = -1;
                    while (inflatedBytes < buffer.Length && bytesReadIteration != 0)
                    {
                        bytesReadIteration = _inflater.Inflate(buffer.Span.Slice(inflatedBytes));
                        inflatedBytes     += bytesReadIteration;
                    }

                    // There are a few different potential states here
                    // 1. DeflateStream or GZipStream that succesfully read bytes => return those bytes
                    // 2. DeflateStream or GZipStream that didn't read bytes and isn't finished => feed more input
                    // 3. DeflateStream that didn't read bytes, but is finished => return 0
                    // 4. GZipStream that is finished but is appended with another gzip stream => feed more input
                    // 5. GZipStream that is finished and appended with garbage => return 0
                    if (inflatedBytes != 0)
                    {
                        // If decompression output buffer is not empty, return immediately.
                        return(inflatedBytes);
                    }
                    else if (_inflater.Finished() && (!_inflater.IsGzipStream() || !_inflater.NeedsInput()))
                    {
                        return(0);
                    }
                    else if (_inflater.NeedsInput())
                    {
                        // We could have read in head information and didn't get any data.
                        // Read from the base stream again.
                        readTask = _stream.ReadAsync(_buffer, cancellationToken);
                    }
                }
            }
            finally
            {
                AsyncOperationCompleting();
            }
        }
Пример #14
0
            public override async ValueTask <int> ReadAsync(Memory <byte> destination, CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (_connection == null || destination.Length == 0)
                {
                    // Response body fully consumed or the caller didn't ask for any data
                    return(0);
                }

                Debug.Assert(_contentBytesRemaining > 0);

                if ((ulong)destination.Length > _contentBytesRemaining)
                {
                    destination = destination.Slice(0, (int)_contentBytesRemaining);
                }

                ValueTask <int> readTask = _connection.ReadAsync(destination);
                int             bytesRead;

                if (readTask.IsCompletedSuccessfully)
                {
                    bytesRead = readTask.Result;
                }
                else
                {
                    CancellationTokenRegistration ctr = _connection.RegisterCancellation(cancellationToken);
                    try
                    {
                        bytesRead = await readTask.ConfigureAwait(false);
                    }
                    catch (Exception exc) when(ShouldWrapInOperationCanceledException(exc, cancellationToken))
                    {
                        throw CreateOperationCanceledException(exc, cancellationToken);
                    }
                    finally
                    {
                        ctr.Dispose();
                    }
                }

                if (bytesRead <= 0)
                {
                    // A cancellation request may have caused the EOF.
                    cancellationToken.ThrowIfCancellationRequested();

                    // Unexpected end of response stream.
                    throw new IOException(SR.net_http_invalid_response);
                }

                Debug.Assert((ulong)bytesRead <= _contentBytesRemaining);
                _contentBytesRemaining -= (ulong)bytesRead;

                if (_contentBytesRemaining == 0)
                {
                    // End of response body
                    _connection.ReturnConnectionToPool();
                    _connection = null;
                }

                return(bytesRead);
            }
Пример #15
0
 public static async Task <object?> Cast(ValueTask <T> source) => await source.ConfigureAwait(false);
Пример #16
0
 public async Task CreateFromValue_Await()
 {
     ValueTask<int> t = new ValueTask<int>(42);
     Assert.Equal(42, await t);
     Assert.Equal(42, await t.ConfigureAwait(false));
     Assert.Equal(42, await t.ConfigureAwait(true));
 }
Пример #17
0
 /// <summary>
 ///  <see cref="System.Runtime.CompilerServices.ConfiguredTaskAwaitable{TResult}.ConfiguredTaskAwaiter"/>を取得します。
 /// </summary>
 /// <returns><see cref="System.Runtime.CompilerServices.ConfiguredTaskAwaitable{TResult}.ConfiguredTaskAwaiter"/>を返します。</returns>
 public ConfiguredValueTaskAwaitable <TResult> .ConfiguredValueTaskAwaiter GetAwaiter()
 {
     return(_task.ConfigureAwait(_continue_on_captured_context).GetAwaiter());
 }
Пример #18
0
 public static ConfiguredValueTaskAwaitable Ignore(this ValueTask task) => task.ConfigureAwait(false);
Пример #19
0
 public static TResult Run <TResult>(this ValueTask <TResult> task, bool continueOnCaputedContext = true)
 => task.ConfigureAwait(continueOnCaputedContext).GetAwaiter().GetResult();
Пример #20
0
 static async Task IgnoreExceptionsAsync(ValueTask <int> task)
 {
     try { await task.ConfigureAwait(false); } catch { }
 }
Пример #21
0
 public static void Run(this ValueTask task, bool continueOnCapturedContext = true)
 => task.ConfigureAwait(continueOnCapturedContext).GetAwaiter().GetResult();
Пример #22
0
        private async ValueTask CompleteConnectAsync(ValueTask task)
        {
            await task.ConfigureAwait(false);

            _active = true;
        }
Пример #23
0
 public static void RunAsync <TResult>(this ValueTask <TResult> task, bool continueOnCapturedContext = false)
 => _ = Task.Run(async() => await task.ConfigureAwait(continueOnCapturedContext));
Пример #24
0
 static async ValueTask <TcpClient> WaitAndWrap(ValueTask <Socket> task) =>
 new TcpClient(await task.ConfigureAwait(false));
 public static ConfiguredValueTaskAwaitable <T> CAF <T>(this ValueTask <T> awaitable) => awaitable.ConfigureAwait(false);
Пример #26
0
 static async ValueTask <Packet> AddContinuation(ValueTask <ArraySegment <byte> > headerBytes, BufferedByteReader bufferedByteReader, IByteHandler byteHandler, Func <int> getNextSequenceNumber, ProtocolErrorBehavior protocolErrorBehavior, IOBehavior ioBehavior) =>
 await ReadPacketAfterHeader(await headerBytes.ConfigureAwait(false), bufferedByteReader, byteHandler, getNextSequenceNumber, protocolErrorBehavior, ioBehavior).ConfigureAwait(false);
 public static ConfiguredValueTaskAwaitable CAF(this ValueTask awaitable) => awaitable.ConfigureAwait(false);
Пример #28
0
 public static ConfiguredValueTaskAwaitable DonotCapture(this ValueTask task)
 {
     return(task.ConfigureAwait(false));
 }
Пример #29
0
 public WithCancellationValueTaskAwaitable(ValueTask <T> task, CancellationToken cancellationToken)
 {
     _awaitable         = task.ConfigureAwait(false);
     _cancellationToken = cancellationToken;
 }
Пример #30
0
 /// <summary>
 /// Make a task execute synchronously
 /// </summary>
 /// <param name="task">Task</param>
 /// <returns>Result</returns>
 public static T Sync <T>(this ValueTask <T> task)
 {
     return(task.ConfigureAwait(false).GetAwaiter().GetResult());
 }
Пример #31
0
            static async ValueTask <IMemoryOwner <byte> > AwaitAndReturnAsync(ValueTask <int> runningTask, byte[] localBuffer, int contentLength)
            {
                await runningTask.ConfigureAwait(false);

                return(new SqsResponseMemoryOwner(localBuffer, contentLength));
            }
Пример #32
0
 public static ConfiguredValueTaskAwaitable NoSync(this ValueTask task)
 {
     return(task.ConfigureAwait(false));
 }
            static async Task <TiffRational[]> TransformValueTaskAsync(ValueTask <TiffValueCollection <TiffRational> > valueTask)
            {
                TiffValueCollection <TiffRational> result = await valueTask.ConfigureAwait(false);

                return(result.GetOrCreateArray());
            }
Пример #34
0
 public async Task CreateFromTask_Await_ConfigureAwaitTrue()
 {
     Task<int> source = Task.Delay(1).ContinueWith(_ => 42);
     ValueTask<int> t = new ValueTask<int>(source);
     Assert.Equal(42, await t.ConfigureAwait(true));
 }
Пример #35
0
        public void ConfiguredAwaiter_OnCompleted(bool continueOnCapturedContext)
        {
            // Since ValueTask implements both OnCompleted and UnsafeOnCompleted,
            // OnCompleted typically won't be used by await, so we add an explicit test
            // for it here.

            ValueTask<int> t = new ValueTask<int>(42);
            var mres = new ManualResetEventSlim();
            t.ConfigureAwait(continueOnCapturedContext).GetAwaiter().OnCompleted(() => mres.Set());
            Assert.True(mres.Wait(10000));
        }