Example #1
0
        public EBCOperation(string name, object eventBasedComponent, IDispatcher dispatcher, AsynchronizerCache asyncerCache) : base(name)
        {
            _eventBasedComponent = eventBasedComponent;
            _dispatcher          = dispatcher;
            _asyncerCache        = asyncerCache;

            _inputPorts = OperationsFactory.Find_input_ports(_eventBasedComponent);
            var outputPorts = OperationsFactory.Find_output_ports(_eventBasedComponent);

            Assign_handlers_to_output_port_events(_eventBasedComponent,
                                                  outputPorts,
                                                  _ =>
            {
                Action <IMessage> continueWith;
                Stack <Action <IMessage> > continuationStack;
                if (_tls.TryGetValue(Thread.CurrentThread, out continuationStack) &&
                    continuationStack.Count > 0)
                {
                    continueWith = continuationStack.Peek();
                }
                else
                {
                    continueWith = _active_continueWith;
                }

                continueWith(_);
            });
        }
Example #2
0
        public static IOperation Schedule_operation_according_to_attributes(AsynchronizerCache asyncerCache, MethodInfo operationMethod, IOperation operation)
        {
            var asyncAttr = operationMethod.GetCustomAttributes(true)
                            .FirstOrDefault(attr => attr.GetType() == typeof(AsyncMethodAttribute))
                            as AsyncMethodAttribute;

            if (asyncAttr != null)
            {
                var asyncer = asyncerCache.Get(asyncAttr.ThreadPoolName, () => new AsynchronizeFIFO());
                return(new AsyncWrapperOperation(asyncer, operation));
            }


            var parallelAttr = operationMethod.GetCustomAttributes(true)
                               .FirstOrDefault(attr => attr.GetType() == typeof(ParallelMethod))
                               as ParallelMethod;

            if (parallelAttr != null)
            {
                var parallelizer = asyncerCache.Get(parallelAttr.ThreadPoolName, () => new Parallelize());
                return(new AsyncWrapperOperation(parallelizer, operation));
            }

            return(operation);
        }
        public void Async_EBC_method_throwing_exception()
        {
            var cache = new AsynchronizerCache();
            var sut   = new EBCOperation("math", new MyAsyncEbc(), null, cache);

            var are = new AutoResetEvent(false);
            FlowRuntimeException result = null;

            var input    = new Message("math.ThrowException", 41);
            var methodOp = sut.Create_method_operation(input);

            methodOp.Implementation(input, _ => { }, ex => { result = ex; are.Set(); });

            Assert.IsTrue(are.WaitOne(1000));
            Assert.IsInstanceOf <ApplicationException>(result.InnerException);
        }
        public void Wrap_parallel_EBC_method()
        {
            var cache = new AsynchronizerCache();
            var sut   = new EBCOperation("math", new MyParallelEbc(), null, cache);

            var      are          = new AutoResetEvent(false);
            IMessage result       = null;
            Thread   methodThread = null;

            var input    = new Message("math.Inc", 41);
            var methodOp = sut.Create_method_operation(input);

            Assert.IsInstanceOf <AsyncWrapperOperation>(methodOp);

            methodOp.Implementation(input, _ => { result = _; methodThread = Thread.CurrentThread; are.Set(); }, _ => { });

            Assert.IsTrue(are.WaitOne(1000));
            Assert.AreEqual(42, (int)result.Data);
            Assert.AreNotSame(methodThread, Thread.CurrentThread);
        }
        public void Stress_test_parallel_method()
        {
            var cache = new AsynchronizerCache();
            var sut   = new EBCOperation("math", new MyParallelEbc(), null, cache);

            var are        = new AutoResetEvent(false);
            var results    = new List <int>();
            var threads    = new Dictionary <long, int>();
            var exceptions = new List <string>();

            const int N = 2000;

            for (var i = 1; i <= N; i++)
            {
                var input    = new Message("math.Inc", i);
                var methodOp = sut.Create_method_operation(input);
                Assert.IsInstanceOf <AsyncWrapperOperation>(methodOp);

                methodOp.Implementation(input, _ =>
                {
                    lock (results)
                    {
                        results.Add((int)_.Data);

                        var thUsage = 0;
                        if (threads.TryGetValue(Thread.CurrentThread.GetHashCode(), out thUsage))
                        {
                            threads[Thread.CurrentThread.GetHashCode()] = thUsage + 1;
                        }
                        else
                        {
                            threads.Add(Thread.CurrentThread.GetHashCode(), 1);
                        }

                        if (results.Count == N)
                        {
                            are.Set();
                        }
                    }
                },
                                        ex =>
                {
                    lock (exceptions)
                    {
                        exceptions.Add(string.Format("data==[{0}] -> {1}", (int)input.Data, ex.ToString()));
                    }
                });
            }

            var waitOne = are.WaitOne(2000);

            Console.WriteLine("count: {0}, thread count: {1}, ex count: {2}", results.Count, threads.Count, exceptions.Count);

            foreach (var th in threads)
            {
                Console.WriteLine("{1} x thread #{0}", th.Key, th.Value);
            }
            Console.WriteLine("thread usage total: {0}", threads.Values.Sum());

            for (var i = 0; i < Math.Min(5, exceptions.Count); i++)
            {
                Console.WriteLine("*** {0}: {1}", i, exceptions[i]);
            }
            Assert.IsTrue(waitOne);
        }
Example #6
0
        // Creating continuations again and again for every output message is very inefficient.
        // But right now it´s simple and serves the purpose. It can be optimized later on.
        public static IOperation Create_method_operation(object instance, MethodInfo operationMethod, AsynchronizerCache asyncerCache)
        {
            var name = operationMethod.Name;
            OperationAdapter implementation;

            if (Is_a_procedure(operationMethod))
            {
                if (operationMethod.GetParameters().Length == 0)
                {
                    implementation = (input, outputCont, _) =>
                    {
                        operationMethod.Invoke(instance, null);
                        outputCont(new Message(name, null, input.CorrelationId));
                    }
                }
                ;
                else
                if (Parameter_types_ok(operationMethod, "c"))
                {
                    implementation = (input, outputCont, _) => operationMethod.Invoke(instance, new[] { Create_continuation(operationMethod.GetParameters()[0], name, input, outputCont) });
                }
                else
                if (Parameter_types_ok(operationMethod, "v"))
                {
                    implementation = (input, outputCont, _) =>
                    {
                        operationMethod.Invoke(instance, new[] { input.Data });
                        outputCont(new Message(name, null, input.CorrelationId));
                    }
                }
                ;
                else
                if (Parameter_types_ok(operationMethod, "cc"))
                {
                    implementation = (input, outputCont, _) => operationMethod.Invoke(instance, new[] { Create_continuation(operationMethod.GetParameters()[0], name + Get_continuation_output_portname(operationMethod.GetParameters()[0]), input, outputCont),
                                                                                                        Create_continuation(operationMethod.GetParameters()[1], name + Get_continuation_output_portname(operationMethod.GetParameters()[1]), input, outputCont) });
                }
                else
                if (Parameter_types_ok(operationMethod, "vc"))
                {
                    implementation = (input, outputCont, _) => operationMethod.Invoke(instance, new[] { input.Data, Create_continuation(operationMethod.GetParameters()[1], name, input, outputCont) });
                }
                else
                if (Parameter_types_ok(operationMethod, "vcc"))
                {
                    implementation = (input, outputCont, _) => operationMethod.Invoke(instance, new[] { input.Data,
                                                                                                        Create_continuation(operationMethod.GetParameters()[1], name + Get_continuation_output_portname(operationMethod.GetParameters()[1]), input, outputCont),
                                                                                                        Create_continuation(operationMethod.GetParameters()[2], name + Get_continuation_output_portname(operationMethod.GetParameters()[2]), input, outputCont) });
                }
                else
                {
                    throw new NotImplementedException(string.Format("{0}.{1}: Procedure signature not supported as an operation!", instance.GetType().Name, operationMethod.Name));
                }
            }
            else
            if (operationMethod.GetParameters().Length == 0)
            {
                implementation = (input, outputCont, _) =>
                {
                    var result = operationMethod.Invoke(instance, null);
                    outputCont(new Message(name, result, input.CorrelationId));
                }
            }
            ;
            else
            if (Parameter_types_ok(operationMethod, "v"))
            {
                implementation = (input, outputCont, _) =>
                {
                    var result = operationMethod.Invoke(instance, new[] { input.Data });
                    outputCont(new Message(name, result, input.CorrelationId));
                }
            }
            ;
            else
            {
                throw new NotImplementedException(string.Format("{0}.{1}: Function signature not supported as an operation!", instance.GetType().Name, operationMethod.Name));
            }


            OperationAdapter exceptionAwareImplementation = (input, outputCont, _) =>
            {
                try
                {
                    implementation(input, outputCont, _);
                }
                catch (TargetInvocationException ex)
                {
                    throw ex.InnerException;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            };

            return(Schedule_operation_according_to_attributes(asyncerCache, operationMethod, new Operation(name, exceptionAwareImplementation)));
        }