|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
namespace System.IO.Pipelines
{
[DebuggerDisplay("IsCompleted = {" + nameof(IsCompleted) + "}")]
internal struct PipeCompletion
{
private static readonly object s_completedSuccessfully = new object();
private object? _state;
private List<PipeCompletionCallback>? _callbacks;
public bool IsCompleted => _state != null;
public bool IsFaulted => _state is ExceptionDispatchInfo;
public PipeCompletionCallbacks? TryComplete(Exception? exception = null)
{
if (_state == null)
{
if (exception != null)
{
_state = ExceptionDispatchInfo.Capture(exception);
}
else
{
_state = s_completedSuccessfully;
}
}
return GetCallbacks();
}
public PipeCompletionCallbacks? AddCallback(Action<Exception?, object?> callback, object? state)
{
_callbacks ??= new List<PipeCompletionCallback>();
_callbacks.Add(new PipeCompletionCallback(callback, state));
if (IsCompleted)
{
return GetCallbacks();
}
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsCompletedOrThrow()
{
if (!IsCompleted)
{
return false;
}
if (_state is ExceptionDispatchInfo edi)
{
edi.Throw();
}
return true;
}
private PipeCompletionCallbacks? GetCallbacks()
{
Debug.Assert(IsCompleted);
var callbacks = _callbacks;
if (callbacks == null)
{
return null;
}
_callbacks = null;
return new PipeCompletionCallbacks(callbacks, _state as ExceptionDispatchInfo);
}
public void Reset()
{
Debug.Assert(IsCompleted);
Debug.Assert(_callbacks == null);
_state = null;
}
public override string ToString()
{
return $"{nameof(IsCompleted)}: {IsCompleted}";
}
}
}
|