Пример #1
0
        /// <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 <T>(this IReadPort <T> from, IWritePort <T> 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;
            }
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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();
            }
        }
Пример #4
0
        /// <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();
            }
        }