Exemplo n.º 1
0
        public void IncrementIfLessThan_ShouldDoNothingIfTheConditionFailes()
        {
            int value = 0;

            Assert.That(InterlockedExtensions.IncrementIfLessThan(ref value, 0) is null);
            Assert.That(value, Is.EqualTo(0));
        }
Exemplo n.º 2
0
        public void IncrementIfLessThan_ShouldWorkParallelly()
        {
            int value = 0;

            Task[] tasks = Enumerable
                           .Repeat(0, 5)
                           .Select(_ => Task.Run(Increment))
                           .ToArray();

            Assert.DoesNotThrowAsync(() => Task.WhenAll(tasks));

            Assert.That(value, Is.EqualTo(5000));

            void Increment()
            {
                for (int i = 0; i < 1000; i++)
                {
                    InterlockedExtensions.IncrementIfLessThan(ref value, 5001);
                }
            }
        }
Exemplo n.º 3
0
        private static int FUsedTasks; // NEM globalis, leszarmazottankent ertelmezett

        private IReadOnlyCollection <object> Dispatch(MethodInfo ifaceMethod, params object?[] args)
        {
            //
            // 1) Ne generaljuk elore le az osszes delegate-et mert nem tudhatjuk h mely metodusok implementacioja
            //    fogja hivni a Dispatch()-et (nem biztos h az osszes).
            // 2) Generikus argumentumot tartalmazo metodushoz amugy sem tudnank legeneralni.
            //

            Func <TInterface, object?[], object> invoke = Cache.GetOrAdd(ifaceMethod, () => ConvertToDelegate(ifaceMethod));

            //
            // Mivel itt a lista egy korabbi allapotaval dolgozunk ezert az iteracio alatt hozzaadott gyermekeken
            // nem, mig eltavolitott gyermekeken meg lesz hivva a cel metodus.
            //

            ICollection <TInterface> children = FChildren.Keys; // masolat

            object[] result = new object[children.Count];

            List <Task> boundTasks = new();

            //
            // Cel metodus hivasa rekurzivan az osszes gyerekre.
            //

            children.ForEach((child, itemIndex) =>
            {
                //
                // Ha van szabad Task akkor az elem es gyermekeinek feldolgozasat elinditjuk azon
                //

                int?taskIndex = InterlockedExtensions.IncrementIfLessThan(ref FUsedTasks, MaxDegreeOfParallelism);

                if (taskIndex is not null)
                {
                    boundTasks.Add(Task.Run(() =>
                    {
                        WriteLine($"{nameof(Dispatch)}(): traversing parallelly ({taskIndex})");
                        try
                        {
                            result[itemIndex] = invoke(child, args);
                        }
                        finally
                        {
                            Interlocked.Decrement(ref FUsedTasks);
                        }
                    }));
                }

                //
                // Kulonben helyben dolgozzuk fel
                //

                else
                {
                    result[itemIndex] = invoke(child, args);
                }
            });

            if (boundTasks.Any())
            {
                Task.WaitAll(boundTasks.ToArray());
            }

            return(result);
        }