wabbajack/Wabbajack.Common.CSP/AChannel.cs
Timothy Baldridge d9ca38cdff
Make BSA Routines async (#168)
* Make BSA routines async
2019-11-11 21:35:07 -07:00

87 lines
2.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Wabbajack.Common.CSP
{
public abstract class AChannel<TIn, TOut> : IChannel<TIn, TOut>
{
public abstract bool IsClosed { get; }
public abstract void Close();
public abstract (AsyncResult, bool) Put(TIn val, Handler<Action<bool>> handler);
public abstract (AsyncResult, TOut) Take(Handler<Action<bool, TOut>> handler);
private Task<(bool, TOut)> _take_cancelled_task;
private Task<(bool, TOut)> TakeCancelledTask
{
get
{
if (_take_cancelled_task == null)
_take_cancelled_task = Task.FromCanceled<(bool, TOut)>(CancellationToken.None);
return _take_cancelled_task;
}
}
private Task<bool> _put_cancelled_task;
private Task<bool> PutCancelledTask
{
get
{
if (_put_cancelled_task == null)
_put_cancelled_task = Task.FromCanceled<bool>(CancellationToken.None);
return _put_cancelled_task;
}
}
public ValueTask<(bool, TOut)> Take(bool onCaller)
{
var handler = new TakeTaskHandler<TOut>();
var (resultType, val) = Take(handler);
switch (resultType)
{
case AsyncResult.Closed:
return new ValueTask<(bool, TOut)>((false, default));
case AsyncResult.Completed:
return new ValueTask<(bool, TOut)>((true, val));
case AsyncResult.Enqueued:
return new ValueTask<(bool, TOut)>(handler.TaskCompletionSource.Task);
case AsyncResult.Canceled:
return new ValueTask<(bool, TOut)>(TakeCancelledTask);
default:
// Should never happen
throw new InvalidDataException();
}
}
public ValueTask<bool> Put(TIn val, bool onCaller)
{
var handler = new PutTaskHandler<bool>();
var (resultType, putResult) = Put(val, handler);
switch (resultType)
{
case AsyncResult.Completed:
return new ValueTask<bool>(putResult);
case AsyncResult.Canceled:
return new ValueTask<bool>(PutCancelledTask);
case AsyncResult.Closed:
return new ValueTask<bool>(false);
case AsyncResult.Enqueued:
return new ValueTask<bool>(handler.TaskCompletionSource.Task);
default:
// Should never happen
throw new InvalidDataException();
}
}
}
}