/// <summary> /// Sets up a simple process that forwards the inputs to the output /// </summary> /// <returns>The gather.</returns> /// <param name="input">Input.</param> /// <param name="output">Output.</param> /// <param name="policy">Policy.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public static Task GatherAsync <T>(IReadChannel <T>[] input, IWriteChannel <T> output, ScatterGatherPolicy policy = ScatterGatherPolicy.Any) { if (input == null || input.Any(x => x == null)) { throw new ArgumentNullException(nameof(input)); } if (output == null) { throw new ArgumentNullException(nameof(output)); } return(AutomationExtensions.RunTask( new { Input = input, Output = output }, async self => { var lst = input.ToList(); while (true) { if (policy == ScatterGatherPolicy.Any) { try { await self.Output.WriteAsync((await lst.ReadFromAnyAsync()).Value); } catch (Exception ex) { if (ex.IsRetiredException()) { var any = false; for (var i = lst.Count - 1; i >= 0; i--) { if (any |= await lst[i].IsRetiredAsync) { lst.RemoveAt(i); } } if (lst.Count > 0 && any) { continue; } } throw; } } else { for (var i = 0; i < lst.Count; i++) { try { await self.Output.WriteAsync(await lst[i].ReadAsync()); } catch (Exception ex) { if (ex.IsRetiredException() && lst.Count > 1) { lst.RemoveAt(i); i--; continue; } throw; } } } } } )); }
/// <summary> /// Sets up a simple process that distributes the input to the output channels /// </summary> /// <returns>An awaitable task.</returns> /// <param name="input">The data source.</param> /// <param name="output">The channels to distribute the data to.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public static Task ScatterAsync <T>(IReadChannel <T> input, IWriteChannel <T>[] output, ScatterGatherPolicy policy = ScatterGatherPolicy.Any) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (output == null || output.Any(x => x == null)) { throw new ArgumentNullException(nameof(output)); } return(AutomationExtensions.RunTask( new { Input = input, Output = output }, async self => { if (policy == ScatterGatherPolicy.Any) { while (true) { await MultiChannelAccess.WriteToAnyAsync(await self.Input.ReadAsync(), self.Output); } } else { var ix = 0; while (true) { await self.Output[ix].WriteAsync(await self.Input.ReadAsync()); ix = (ix + 1) % output.Length; } } } )); }