Exemplo n.º 1
0
 public void TryAgainAfterOptomisticMissDelay()
 {
     Assert.IsTrue(InterlockedExtensions.TryAgainAfterOptomisticMissDelay(0));
     Assert.IsTrue(InterlockedExtensions.TryAgainAfterOptomisticMissDelay(3));
     Assert.IsTrue(InterlockedExtensions.TryAgainAfterOptomisticMissDelay(5));
     Assert.IsFalse(InterlockedExtensions.TryAgainAfterOptomisticMissDelay(10));
 }
Exemplo n.º 2
0
        /// <summary>
        ///   Checks whether the model's invariant holds for all states.
        /// </summary>
        internal void Check()
        {
            try
            {
                while (_context.LoadBalancer.LoadBalance(_index))
                {
                    int state;
                    if (!_stateStack.TryGetState(out state))
                    {
                        continue;
                    }

                    CallStateDetectionEventInDebugMode(state);

                    HandleTransitions(Model.GetSuccessorTransitions(_context.States[state]), state, isInitial: false);

                    InterlockedExtensions.ExchangeIfGreaterThan(ref _context.LevelCount, _stateStack.FrameCount, _stateStack.FrameCount);
                    _context.ReportProgress();
                }
            }
            catch (Exception e)
            {
                _context.LoadBalancer.Terminate();
                _context.Exception = e;

                if (!(e is OutOfMemoryException))
                {
                    CreateCounterExample(endsWithException: true, addAdditionalState: true);
                }
            }
        }
Exemplo n.º 3
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.º 4
0
 /// <summary>
 ///   Prints a progress report if necessary.
 /// </summary>
 public void ReportProgress()
 {
     if (InterlockedExtensions.ExchangeIfGreaterThan(ref NextReport, StateCount, NextReport + ReportStateCountDelta))
     {
         Report();
     }
 }
Exemplo n.º 5
0
        /// <summary>
        ///   Adds the <paramref name="state" /> to the cache if it is not already known. Returns <c>true</c> to indicate that the state
        ///   has been added. This method can be called simultaneously from multiple threads.
        /// </summary>
        /// <param name="state">The state that should be added.</param>
        /// <param name="index">Returns the unique index of the state.</param>
        public override bool AddState(byte *state, out int index)
        {
            // We don't have to do any out of bounds checks here

            var hash = MemoryBuffer.Hash(state, _stateVectorSize, 0);

            for (var i = 1; i < ProbeThreshold; ++i)
            {
                // We store 30 bit hash values as 32 bit integers, with the most significant bit #31 being set
                // indicating the 'written' state and bit #30 indicating whether writing is not yet finished
                // 'empty' is represented by 0
                // We ignore two most significant bits of the original hash, which has no influence on the
                // correctness of the algorithm, but might result in more state comparisons
                var hashedIndex    = MemoryBuffer.Hash((byte *)&hash, sizeof(int), i * 8345723) % _cachedStatesCapacity;
                var memoizedHash   = hashedIndex & 0x3FFFFFFF;
                var cacheLineStart = (hashedIndex / BucketsPerCacheLine) * BucketsPerCacheLine;

                for (var j = 0; j < BucketsPerCacheLine; ++j)
                {
                    var offset       = (int)(cacheLineStart + (hashedIndex + j) % BucketsPerCacheLine);
                    var currentValue = Volatile.Read(ref _hashMemory[offset]);

                    if (currentValue == 0 && Interlocked.CompareExchange(ref _hashMemory[offset], (int)memoizedHash | (1 << 30), 0) == 0)
                    {
                        var freshCompactIndex = InterlockedExtensions.IncrementReturnOld(ref _savedStates);
                        Volatile.Write(ref _indexMapperMemory[offset], freshCompactIndex);

                        MemoryBuffer.Copy(state, this[freshCompactIndex], _stateVectorSize);
                        Volatile.Write(ref _hashMemory[offset], (int)memoizedHash | (1 << 31));


                        index = freshCompactIndex;
                        return(true);
                    }

                    // We have to read the hash value again as it might have been written now where it previously was not
                    currentValue = Volatile.Read(ref _hashMemory[offset]);
                    if ((currentValue & 0x3FFFFFFF) == memoizedHash)
                    {
                        while ((currentValue & 1 << 31) == 0)
                        {
                            currentValue = Volatile.Read(ref _hashMemory[offset]);
                        }

                        var compactIndex = Volatile.Read(ref _indexMapperMemory[offset]);

                        if (compactIndex != -1 && MemoryBuffer.AreEqual(state, this[compactIndex], _stateVectorSize))
                        {
                            index = compactIndex;
                            return(false);
                        }
                    }
                }
            }

            throw new OutOfMemoryException(
                      "Failed to find an empty hash table slot within a reasonable amount of time. Try increasing the state capacity.");
        }
Exemplo n.º 6
0
        public void InterlockedMinDouble()
        {
            double x = 0;

            Assert.AreEqual(0, InterlockedExtensions.TryOptomisticMin(ref x, 1));

            x = 0;
            Assert.AreEqual(-1, InterlockedExtensions.TryOptomisticMin(ref x, -1));
        }
Exemplo n.º 7
0
        public void InterlockedMinLong()
        {
            long x = 0;

            Assert.AreEqual(0, InterlockedExtensions.TryOptomisticMin(ref x, 1));

            x = 0;
            Assert.AreEqual(-1, InterlockedExtensions.TryOptomisticMin(ref x, -1));
        }
        private long GetPlaceForNewTransitionChainElements(long number)
        {
            var locationOfFirstNewEntry = InterlockedExtensions.AddFetch(ref _transitionChainElementCount, number);

            if (locationOfFirstNewEntry + number >= _maxNumberOfTransitions)
            {
                throw new OutOfMemoryException("Unable to store transitions. Try increasing the transition capacity.");
            }
            return(locationOfFirstNewEntry);
        }
Exemplo n.º 9
0
        private int GetPlaceForNewTransitionTargetElement()
        {
            var locationOfNewEntry = InterlockedExtensions.IncrementReturnOld(ref _transitionTargetCount);

            if (locationOfNewEntry >= _maxNumberOfTransitionTargets)
            {
                throw new OutOfMemoryException("Unable to store distribution.");
            }
            return(locationOfNewEntry);
        }
Exemplo n.º 10
0
        private long GetPlaceForNewTransitionTargetElement()
        {
            var locationOfNewEntry = InterlockedExtensions.IncrementReturnOld(ref _transitionTargetCount);

            if (locationOfNewEntry >= _maxNumberOfTransitionTargets)
            {
                throw new OutOfMemoryException($"Unable to transition target (limit is {_maxNumberOfTransitionTargets} entries)");
            }
            return(locationOfNewEntry);
        }
Exemplo n.º 11
0
        private int GetPlaceForNewTransitionChainElement()
        {
            var locationOfNewEntry = InterlockedExtensions.IncrementReturnOld(ref _transitionChainElementCount);

            if (locationOfNewEntry >= _maxNumberOfTransitions)
            {
                throw new OutOfMemoryException("Unable to store transitions. Try increasing the transition capacity.");
            }
            return(locationOfNewEntry);
        }
Exemplo n.º 12
0
        private long GetPlaceForNewContinuationGraphElements(int number)
        {
            var locationOfFirstNewEntry = InterlockedExtensions.AddFetch(ref _continuationGraphElementCount, number);

            if (locationOfFirstNewEntry >= _maxNumberOfContinuationGraphElements)
            {
                throw new OutOfMemoryException("Unable to store transitions. Try increasing the transition capacity.");
            }
            return(locationOfFirstNewEntry);
        }
Exemplo n.º 13
0
        private long GetPlaceForNewContinuationGraphElements(int number)
        {
            var locationOfFirstNewEntry = InterlockedExtensions.AddFetch(ref _continuationGraphElementCount, number);

            if (locationOfFirstNewEntry + number >= _maxNumberOfContinuationGraphElements)
            {
                throw new OutOfMemoryException($"Unable to store continuation graph element (limit is {_maxNumberOfContinuationGraphElements} entries)");
            }
            return(locationOfFirstNewEntry);
        }
        public void InterlockedAnd()
        {
            // 32-bit test
            int value1  = 0x11023304;
            int result1 = InterlockedExtensions.And(ref value1, 0x10203040);

            Assert.Equal(0x10003000, value1);
            Assert.Equal(0x10003000, result1);

            // 64-bit test
            long value2  = 0x1102330455067708;
            long result2 = InterlockedExtensions.And(ref value2, 0x1020304050607080);

            Assert.Equal(0x1000300050007000, value2);
            Assert.Equal(0x1000300050007000, result2);
        }
        public void InterlockedOr()
        {
            // 32-bit test
            int value1  = 0x01020304;
            int result1 = InterlockedExtensions.Or(ref value1, 0x10203040);

            Assert.Equal(0x11223344, value1);
            Assert.Equal(0x11223344, result1);

            // 64-bit test
            long value2  = 0x0102030405060708;
            long result2 = InterlockedExtensions.Or(ref value2, 0x1020304050607080);

            Assert.Equal(0x1122334455667788, value2);
            Assert.Equal(0x1122334455667788, result2);
        }
Exemplo n.º 16
0
        /// <summary>
        ///   Reserve a state index in StateStorage. Must not be called after AddState has been called.
        /// </summary>
        internal override int ReserveStateIndex()
        {
            var freshCompactIndex = InterlockedExtensions.IncrementReturnOld(ref _savedStates);

            // Use the index pointing at the last possible element in the buffers and decrease the size.
            _reservedStatesCapacity++;
            _cachedStatesCapacity--;

            // Add BucketsPerCacheLine so returnIndex does not interfere with the maximal possible index returned by AddState
            // which is _cachedStatesCapacity+BucketsPerCacheLine-1.
            // returnIndex is in range of capacityToReserve, so this is save.
            var hashBasedIndex = _cachedStatesCapacity + BucketsPerCacheLine;

            Volatile.Write(ref _indexMapperMemory[hashBasedIndex], freshCompactIndex);

            Assert.InRange(hashBasedIndex, 0, Int32.MaxValue);
            Assert.InRange(hashBasedIndex, 0, _totalCapacity + BucketsPerCacheLine);
            return((int)freshCompactIndex);
        }
Exemplo n.º 17
0
        /// <summary>
        ///   Adds the <paramref name="state" /> and all of its <see cref="transitions" /> to the state graph.
        /// </summary>
        /// <param name="state">The state that should be added.</param>
        /// <param name="isInitial">Indicates whether the state is an initial state.</param>
        /// <param name="transitions">The transitions leaving the state.</param>
        /// <param name="transitionCount">The number of valid transitions leaving the state.</param>
        internal void AddStateInfo(int state, bool isInitial, TransitionCollection transitions, int transitionCount)
        {
            Assert.That(!isInitial || _initialTransitionCount == 0, "Initial transitions can only be added once.");

            if (isInitial)
            {
                _initialTransitionCount = transitionCount;
            }
            else
            {
                Interlocked.Increment(ref _stateCount);
            }

            Interlocked.Add(ref _transitionCount, transitionCount);

            // Transitions are synchronized by atomatically incrementing the offset counter
            var offset = InterlockedExtensions.AddFetch(ref _transitionOffset, transitionCount);

            if (offset + transitionCount > _transitionCapacity)
            {
                throw new OutOfMemoryException("Unable to store transitions. Try increasing the transition capacity.");
            }

            // No need to synchronize state addition, as all states are only discovered once
            if (!isInitial)
            {
                _stateMap[state] = new TransitionRange {
                    StartIndex = offset, Count = transitionCount
                }
            }
            ;

            // Copy the transitions into the buffer
            foreach (var transition in transitions)
            {
                Assert.That(TransitionFlags.IsValid(transition->Flags), "Attempted to add an invalid transition.");

                MemoryBuffer.Copy((byte *)transition, _transitions + offset * TransitionSize, TransitionSize);
                ++offset;
            }
        }
Exemplo n.º 18
0
        public void DecrementIfGreaterThan_ShouldWorkParallelly()
        {
            int value = 5000;

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

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

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

            void Decrement()
            {
                for (int i = 0; i < 1000; i++)
                {
                    InterlockedExtensions.DecrementIfGreaterThan(ref value, -1);
                }
            }
        }
Exemplo n.º 19
0
        public void InterlockedExponentialMovingAverage()
        {
            double x = 0;

            Assert.AreEqual(0.0, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 0.0, 1.0));
            Assert.AreEqual(0.5, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 1.0, 1.0));
            Assert.AreEqual(0.5, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 0.0, 1.0));
            Assert.AreEqual(0.75, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 1.0, 1.0));
            Assert.AreEqual(0.75, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 0.0, 1.0));
            Assert.AreEqual(0.875, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 1.0, 1.0));
            Assert.AreEqual(0.875, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 0.0, 1.0));

            x = 0;
            Assert.AreEqual(0.75, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 2.0, 1.0));
            Assert.AreEqual(0.9375, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, 2.0, 1.0));

            x = 0;
            double halfHalfLife = Math.Log(4.0 / 3.0) / Math.Log(2.0);

            Assert.AreEqual(0.25, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, halfHalfLife, 1.0));
            Assert.AreEqual(0.4375, InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, halfHalfLife, 1.0));

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => InterlockedExtensions.TryOptomisticAddExponentialMovingAverageSample(ref x, -0.0000001, 1.0));
        }
Exemplo n.º 20
0
        private void RunTest(ExperimentInfo experimentInfo, ref int stop1, ref int stop2, ref int stop3, ref int stop4,
                             ref double sumOfDeltaCmax, ref float deltaCmaxMax, ref double offlineExecutionTimeInMilliseconds,
                             ref double onlineExecutionTimeInMilliseconds,
                             ref int offlineResolvedConflictAmount, ref int onlineResolvedConflictAmount,
                             ref int onlineUnResolvedConflictAmount, ref int downtimeAmount)
        {
            var offlineResult = OfflineExecutor.RunInOffline(experimentInfo);

            if (experimentInfo.J12Chain == null || experimentInfo.J12.Any() && !experimentInfo.J12Chain.Any())
            {
                experimentInfo.J12Chain = new Chain(experimentInfo.J12);
                // new Chain(experimentInfo.J12.Select(d => new LaboriousDetail(d.OnFirst, d.OnSecond, d.Number)));
            }


            if (experimentInfo.J21Chain == null || experimentInfo.J21.Any() && !experimentInfo.J21Chain.Any())
            {
                experimentInfo.J21Chain = new Chain(experimentInfo.J21);
                // new Chain(experimentInfo.J21.Select(d => new LaboriousDetail(d.OnFirst, d.OnSecond, d.Number)));
            }

            if (!offlineResult)
            {
                experimentInfo.OnlineChainOnFirstMachine  = GetOnlineChainOnFirstMachine(experimentInfo);
                experimentInfo.OnlineChainOnSecondMachine = GetOnlineChainOnSecondMachine(experimentInfo);

                RunOnlineMode(experimentInfo);

                if (!experimentInfo.Result.Online.IsResolvedOnCheck3InOnline)
                {
                    Interlocked.Increment(ref stop2);
                }
                else if (experimentInfo.Result.IsStop3OnOnline)
                {
                    Interlocked.Increment(ref stop3);
                }
                else
                {
                    Interlocked.Increment(ref stop4);
                    InterlockedExtensions.Add(ref sumOfDeltaCmax, experimentInfo.Result.DeltaCmax);
                    InterlockedExtensions.Max(ref deltaCmaxMax, experimentInfo.Result.DeltaCmax);
                }

                Interlocked.Add(ref downtimeAmount,
                                experimentInfo.OnlineChainOnFirstMachine.Count(x => x.Type == OnlineChainType.Downtime) +
                                experimentInfo.OnlineChainOnSecondMachine.Count(x => x.Type == OnlineChainType.Downtime));
            }
            else
            {
                Interlocked.Increment(ref stop1);
            }

            InterlockedExtensions.Add(ref offlineExecutionTimeInMilliseconds,
                                      experimentInfo.Result.OfflineExecutionTime.TotalMilliseconds);
            InterlockedExtensions.Add(ref onlineExecutionTimeInMilliseconds,
                                      experimentInfo.Result.Online.ExecutionTime.TotalMilliseconds);

            Interlocked.Add(ref offlineResolvedConflictAmount, experimentInfo.Result.OfflineResolvedConflictAmount);
            Interlocked.Add(ref onlineResolvedConflictAmount, experimentInfo.Result.Online.ResolvedConflictAmount);
            Interlocked.Add(ref onlineUnResolvedConflictAmount,
                            experimentInfo.Result.Online.UnresolvedConflictAmount);
        }
Exemplo n.º 21
0
        public void InterlockedAddDouble()
        {
            double x = Double.MaxValue - 5;

            Assert.AreEqual(Double.MaxValue, InterlockedExtensions.TryOptomisticAdd(ref x, 5));
        }
Exemplo n.º 22
0
        public Task <string?> RequestAsync(MethodId methodId, object? @internal = null, object?data = null)
        {
            if (_closed)
            {
                throw new InvalidStateException("Channel closed");
            }

            var method = methodId.GetEnumStringValue();
            var id     = InterlockedExtensions.Increment(ref _nextId);
            // NOTE: For testinng
            //_logger.LogDebug($"RequestAsync() | [Method:{method}, Id:{id}]");

            var requestMesssge = new RequestMessage
            {
                Id       = id,
                Method   = method,
                Internal = @internal,
                Data     = data,
            };
            var nsBytes = Netstring.Encode(requestMesssge.ToCamelCaseJson());

            if (nsBytes.Length > NsMessageMaxLen)
            {
                throw new Exception("Channel request too big");
            }

            var tcs = new TaskCompletionSource <string?>();

            var sent = new Sent
            {
                RequestMessage = requestMesssge,
                Resolve        = data =>
                {
                    if (!_sents.TryRemove(id, out var _))
                    {
                        tcs.TrySetException(new Exception($"Received response does not match any sent request [id:{id}]"));
                        return;
                    }
                    tcs.TrySetResult(data);
                },
                Reject = e =>
                {
                    if (!_sents.TryRemove(id, out var _))
                    {
                        tcs.TrySetException(new Exception($"Received response does not match any sent request [id:{id}]"));
                        return;
                    }
                    tcs.TrySetException(e);
                },
                Close = () =>
                {
                    tcs.TrySetException(new InvalidStateException("Channel closed"));
                },
            };

            if (!_sents.TryAdd(id, sent))
            {
                throw new Exception($"Error add sent request [id:{id}]");
            }

            tcs.WithTimeout(TimeSpan.FromSeconds(15 + (0.1 * _sents.Count)), () => _sents.TryRemove(id, out var _));

            Loop.Default.Sync(() =>
            {
                try
                {
                    // This may throw if closed or remote side ended.
                    _producerSocket.Write(nsBytes, ex =>
                    {
                        if (ex != null)
                        {
                            _logger.LogError(ex, "_producerSocket.Write() | Error");
                            sent.Reject(ex);
                        }
                    });
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "_producerSocket.Write() | Error");
                    sent.Reject(ex);
                }
            });

            return(tcs.Task);
        }
Exemplo n.º 23
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);
        }