Пример #1
0
        /// <summary>
        /// Creates an asynchronous computation that executes all the given asynchronous computations, initially queueing each as work items and using a fork/join pattern.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static Async <ImmutableList <T> > Parallel <T>(this ImmutableList <Async <T> > ms)
        {
            var empty = new ImmutableList <T>();

            return(() =>
            {
                var num = (uint)Math.Min(8, ms.Count);  // 64 is maximum here
                if (num == 0)
                {
                    return empty;
                }

                var xs = ms.Take(num);
                var rest = ms.RemoveRange(0, (int)num);
                var asyncs = xs.Map(x =>
                {
                    var handle = new AsyncEventHandle <T>();
                    x.Bind <T, Unit>(v => () => handle.Complete(v)).Start();
                    return handle;
                });
                WaitHandle.WaitAll(asyncs.Map(ah => (WaitHandle)ah.DoneEvent).ToArray());
                var ps = asyncs.Map(x => x.Result());
                return empty.AddRange(rest.Count > 0 ? ps.AddRange(rest.Parallel().RunSynchronously()) : ps);
            });
        }
Пример #2
0
        /// <summary>
        ///     Posts a message to an agent and await a reply on the channel, synchronously.
        /// </summary>
        /// <param name="f">The lambda providing the message.</param>
        /// <returns>The agents reply</returns>
        public TReply PostAndReply(Func <AsyncReplyChannel <TReply>, TMessage> f)
        {
            var handle = new AsyncEventHandle <TReply>();

            Post(f(new AsyncReplyChannel <TReply>(handle.Complete)));
            handle.DoneEvent.WaitOne();
            return(handle.Result());
        }
Пример #3
0
 /// <summary>
 /// Starts a child computation. This allows multiple asynchronous computations to be executed simultaneously.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="m"></param>
 /// <returns>A new computation that waits for the input computation to finish.</returns>
 public static Async <Async <T> > StartChild <T>(this Async <T> m)
 {
     return(() =>
     {
         var handle = new AsyncEventHandle <T>();
         m.StartAndReply(ch => new AsyncReplyChannel <T>(r =>
         {
             ch.Reply(r);
             handle.Complete(r);
             return Unit.Default;
         }));
         return () =>
         {
             handle.DoneEvent.WaitOne();
             return handle.Result();
         };
     });
 }
Пример #4
0
        /// <summary>
        /// Creates an asynchronous computation that executes all the given asynchronous computations, initially queueing each as work items and using a fork/join pattern.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ms"></param>
        /// <returns></returns>
        public static Async <IEnumerable <T> > Parallel <T>(this IEnumerable <Async <T> > ls)
        {
            return(() =>
            {
                var ms = System.Collections.Immutable.ImmutableList.ToImmutableList(ls);
                var num = Math.Min(8, ms.Count); // 64 is maximum here
                if (num == 0)
                {
                    return System.Collections.Immutable.ImmutableList <T> .Empty;
                }

                var xs = ms.GetRange(0, num);
                var rest = ms.RemoveRange(0, num);
                var asyncs = xs.Select(x =>
                {
                    var handle = new AsyncEventHandle <T>();
                    x.Bind <T, Unit>(v => () => handle.Complete(v)).Start();
                    return handle;
                }).ToImmutableList();
                WaitHandle.WaitAll(asyncs.Select(ah => (WaitHandle)ah.DoneEvent).ToArray());
                var ps = asyncs.Select(x => x.Result());
                return System.Collections.Immutable.ImmutableList <T> .Empty.AddRange(ps).AddRange(rest.Parallel().RunSynchronously());
            });
        }