wabbajack/Wabbajack.Common/CSP/CSPExtensions.cs
2019-11-10 20:47:25 -07:00

129 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms.VisualStyles;
namespace Wabbajack.Common.CSP
{
public static class CSPExtensions
{
public static async Task OntoChannel<TIn, TOut>(this IEnumerable<TIn> coll, IChannel<TIn, TOut> chan)
{
foreach (var val in coll)
{
if (!await chan.Put(val)) break;
}
}
/// <summary>
/// Turns a IEnumerable collection into a channel. Note, computation of the enumerable will happen inside
/// the lock of the channel, so try to keep the work of the enumerable light.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="coll">Collection to spool out of the channel.</param>
/// <returns></returns>
public static IChannel<T, T> ToChannel<T>(this IEnumerable<T> coll)
{
var chan = Channel.Create(coll.GetEnumerator());
chan.Close();
return chan;
}
/// <summary>
/// Takes all the values from chan, once the channel closes returns a List of the values taken.
/// </summary>
/// <typeparam name="TOut"></typeparam>
/// <typeparam name="TIn"></typeparam>
/// <param name="chan"></param>
/// <returns></returns>
public static async Task<List<TOut>> TakeAll<TOut, TIn>(this IChannel<TIn, TOut> chan)
{
List<TOut> acc = new List<TOut>();
while (true)
{
var (open, val) = await chan.Take();
if (!open) break;
acc.Add(val);
}
return acc;
}
/// <summary>
/// Pipes values from `from` into `to`
/// </summary>
/// <typeparam name="TIn"></typeparam>
/// <typeparam name="TMid"></typeparam>
/// <typeparam name="TOut"></typeparam>
/// <param name="from">source channel</param>
/// <param name="to">destination channel</param>
/// <param name="closeOnFinished">Tf true, will close the other channel when one channel closes</param>
/// <returns></returns>
public static async Task Pipe<TIn, TMid, TOut>(this IChannel<TIn, TMid> from, IChannel<TMid, TOut> to, bool closeOnFinished = true)
{
while (true)
{
var (isFromOpen, val) = await from.Take();
if (isFromOpen)
{
var isToOpen = await to.Put(val);
if (isToOpen) continue;
if (closeOnFinished)
@from.Close();
break;
}
if (closeOnFinished)
to.Close();
break;
}
}
public static Task<T> ThreadedTask<T>(Func<T> action)
{
var src = new TaskCompletionSource<T>();
var th = new Thread(() =>
{
try
{
src.SetResult(action());
}
catch (Exception ex)
{
src.SetException(ex);
}
}) {Priority = ThreadPriority.BelowNormal};
th.Start();
return src.Task;
}
public static Task ThreadedTask<T>(Action action)
{
var src = new TaskCompletionSource<bool>();
var th = new Thread(() =>
{
try
{
action();
src.SetResult(true);
}
catch (Exception ex)
{
src.SetException(ex);
}
})
{ Priority = ThreadPriority.BelowNormal };
th.Start();
return src.Task;
}
}
}