public static IReadPort <TOut> Select <TIn, TOut>(this IReadPort <TIn> from, Func <TIn, Task <TOut> > f, bool propagateClose = true) { var to = Channel.Create <TOut>(4); Task.Run(async() => { try { while (true) { var(is_open_src, val) = await from.Take(); if (!is_open_src) { break; } var is_open_dest = await to.Put(await f(val)); if (!is_open_dest) { break; } } } finally { if (propagateClose) { from.Close(); to.Close(); } } }); return(to); }
public static IReadPort <TOut> UnorderedPipelineSync <TIn, TOut>( this IReadPort <TIn> from, Func <TIn, TOut> f, bool propagateClose = true) { var parallelism = Environment.ProcessorCount; var to = Channel.Create <TOut>(parallelism * 2); async Task Pump() { while (true) { var(is_open, job) = await from.Take(); if (!is_open) { break; } try { var putIsOpen = await to.Put(f(job)); if (!putIsOpen) { return; } } catch (Exception) { // ignored } } } Task.Run(async() => { await Task.WhenAll(Enumerable.Range(0, parallelism) .Select(idx => Task.Run(Pump))); if (propagateClose) { from.Close(); to.Close(); } }); return(to); }
public static async Task UnorderedThreadedPipeline <TIn, TOut>( this IReadPort <TIn> from, int parallelism, IWritePort <TOut> to, Func <TIn, TOut> f, bool propagateClose = true) { Task Pump() { var tcs = new TaskCompletionSource <bool>(); var th = new Thread(() => { while (true) { var(is_open, job) = from.Take().Result; if (!is_open) { break; } var putIsOpen = to.Put(f(job)).Result; if (!putIsOpen) { return; } } tcs.SetResult(true); }) { Priority = ThreadPriority.BelowNormal }; th.Start(); return(tcs.Task); } await Task.WhenAll(Enumerable.Range(0, parallelism) .Select(idx => Task.Run(Pump))); if (propagateClose) { from.Close(); to.Close(); } }
public static async Task UnorderedPipeline <TIn, TOut>( this IReadPort <TIn> from, int parallelism, IWritePort <TOut> to, Func <TIn, Task <TOut> > f, bool propagateClose = true) { async Task Pump() { while (true) { var(is_open, job) = await from.Take(); if (!is_open) { break; } var putIsOpen = await to.Put(await f(job)); if (!putIsOpen) { return; } } } await Task.WhenAll(Enumerable.Range(0, parallelism) .Select(idx => Task.Run(Pump))); if (propagateClose) { from.Close(); to.Close(); } }
/// <summary> /// Creates a pipeline that takes items from `from` transforms them with the pipeline given by `transform` and puts /// the resulting values onto `to`. The pipeline may create 0 or more items for every input item and they will be /// spooled onto `to` in a undefined order. `n` determines how many parallel tasks will be running at once. Each of /// these tasks maintains its own transformation pipeline, so `transform` will be called once for every `n`. Completing /// a `transform` pipeline has no effect. /// </summary> /// <typeparam name="TInSrc"></typeparam> /// <typeparam name="TOutSrc"></typeparam> /// <typeparam name="TInDest"></typeparam> /// <typeparam name="TOutDest"></typeparam> /// <param name="from"></param> /// <param name="parallelism"></param> /// <param name="to"></param> /// <param name="transform"></param> /// <param name="propagateClose"></param> /// <returns></returns> public static async Task UnorderedPipeline <TIn, TOut>( this IReadPort <TIn> from, int parallelism, IWritePort <TOut> to, Func <IObservable <TIn>, IObservable <TOut> > transform, bool propagateClose = true) { async Task Pump() { var pipeline = new Subject <TIn>(); var buffer = new List <TOut>(); var dest = transform(pipeline); dest.Subscribe(itm => buffer.Add(itm)); while (true) { var(is_open, tval) = await from.Take(); if (is_open) { pipeline.OnNext(tval); foreach (var pval in buffer) { var is_put_open = await to.Put(pval); if (is_put_open) { continue; } if (propagateClose) { @from.Close(); } return; } buffer.Clear(); } else { pipeline.OnCompleted(); if (buffer.Count > 0) { foreach (var pval in buffer) { if (!await to.Put(pval)) { break; } } } break; } } } await Task.WhenAll(Enumerable.Range(0, parallelism) .Select(idx => Task.Run(Pump))); if (propagateClose) { from.Close(); to.Close(); } }