2019-11-09 06:37:05 +00:00
|
|
|
|
using System;
|
2019-11-09 14:49:00 +00:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Threading;
|
2019-11-09 06:37:05 +00:00
|
|
|
|
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();
|
2019-11-09 14:49:00 +00:00
|
|
|
|
public abstract (AsyncResult, bool) Put(TIn val, Handler<Action<bool>> handler);
|
2019-11-09 21:29:55 +00:00
|
|
|
|
public abstract (AsyncResult, TOut) Take(Handler<Action<bool, TOut>> handler);
|
2019-11-09 06:37:05 +00:00
|
|
|
|
|
2019-11-09 14:49:00 +00:00
|
|
|
|
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
|
2019-11-09 06:37:05 +00:00
|
|
|
|
{
|
2019-11-09 14:49:00 +00:00
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_put_cancelled_task == null)
|
|
|
|
|
_put_cancelled_task = Task.FromCanceled<bool>(CancellationToken.None);
|
|
|
|
|
return _put_cancelled_task;
|
|
|
|
|
}
|
2019-11-09 06:37:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-09 14:49:00 +00:00
|
|
|
|
public ValueTask<(bool, TOut)> Take(bool onCaller)
|
2019-11-09 06:37:05 +00:00
|
|
|
|
{
|
2019-11-09 14:49:00 +00:00
|
|
|
|
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();
|
|
|
|
|
}
|
2019-11-09 06:37:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|