Пример #1
0
        public void ShouldWaitForWorkCompleteWhereAllWorkersAreBlockedOnRingBuffer()
        {
            const long expectedNumberMessages = 10;

            FillRingBuffer(expectedNumberMessages);

            var workers = new StubEventProcessor[3];

            for (var i = 0; i < workers.Length; i++)
            {
                workers[i] = new StubEventProcessor(expectedNumberMessages - 1);
            }

            var dependencyBarrier = _ringBuffer.NewBarrier(DisruptorUtil.GetSequencesFor(workers));

            Task.Run(() =>
            {
                var sequence = _ringBuffer.Next();
                _ringBuffer[sequence].Value = (int)sequence;
                _ringBuffer.Publish(sequence);

                foreach (var stubWorker in workers)
                {
                    stubWorker.Sequence.SetValue(sequence);
                }
            });

            const long expectedWorkSequence  = expectedNumberMessages;
            var        completedWorkSequence = dependencyBarrier.WaitFor(expectedNumberMessages);

            Assert.IsTrue(completedWorkSequence >= expectedWorkSequence);
        }
Пример #2
0
        public long GetRemainingCapacity()
        {
            var consumed = DisruptorUtil.GetMinimumSequence(Volatile.Read(ref _gatingSequences), _cursor.Value);
            var produced = _cursor.Value;

            return(BufferSize - (produced - consumed));
        }
Пример #3
0
        public void ShouldWaitForWorkCompleteWhereCompleteWorkThresholdIsBehind()
        {
            const long expectedNumberMessages = 10;

            FillRingBuffer(expectedNumberMessages);

            var eventProcessors = new StubEventProcessor[3];

            for (var i = 0; i < eventProcessors.Length; i++)
            {
                eventProcessors[i] = new StubEventProcessor(expectedNumberMessages - 2);
            }

            var eventProcessorBarrier = _ringBuffer.NewBarrier(DisruptorUtil.GetSequencesFor(eventProcessors));

            Task.Factory.StartNew(() =>
            {
                foreach (var stubWorker in eventProcessors)
                {
                    stubWorker.Sequence.SetValue(stubWorker.Sequence.Value + 1);
                }
            }).Wait();

            const long expectedWorkSequence  = expectedNumberMessages - 1;
            var        completedWorkSequence = eventProcessorBarrier.WaitFor(expectedWorkSequence);

            Assert.IsTrue(completedWorkSequence >= expectedWorkSequence);
        }
Пример #4
0
        internal long NextInternal(int n)
        {
            long current;
            long next;

            var spinWait = default(AggressiveSpinWait);

            do
            {
                current = _cursor.Value;
                next    = current + n;

                long wrapPoint            = next - _bufferSize;
                long cachedGatingSequence = _gatingSequenceCache.Value;

                if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current)
                {
                    long gatingSequence = DisruptorUtil.GetMinimumSequence(Volatile.Read(ref _gatingSequences), current);

                    if (wrapPoint > gatingSequence)
                    {
                        spinWait.SpinOnce();
                        continue;
                    }

                    _gatingSequenceCache.SetValue(gatingSequence);
                }
                else if (_cursor.CompareAndSet(current, next))
                {
                    break;
                }
            } while (true);

            return(next);
        }
        public MultiProducerSequencerRef2(int bufferSize, IWaitStrategy waitStrategy)
        {
            if (bufferSize < 1)
            {
                throw new ArgumentException("bufferSize must not be less than 1");
            }
            if (!bufferSize.IsPowerOf2())
            {
                throw new ArgumentException("bufferSize must be a power of 2");
            }

            _bufferSize             = bufferSize;
            _waitStrategy           = waitStrategy;
            _isBlockingWaitStrategy = !(waitStrategy is INonBlockingWaitStrategy);
#if NETCOREAPP
            _availableBuffer        = GC.AllocateArray <int>(bufferSize, pinned: true);
            _availableBufferPointer = (int *)Unsafe.AsPointer(ref _availableBuffer[0]);
#else
            _availableBuffer = new int[bufferSize];
#endif
            _indexMask  = bufferSize - 1;
            _indexShift = DisruptorUtil.Log2(bufferSize);

            InitialiseAvailableBuffer();
        }
Пример #6
0
        /// <summary>
        /// Set up custom event processors to handle events from the ring buffer. The disruptor will
        /// automatically start this processors when <see cref="Start"/> is called.
        ///
        /// This method can be used as the start of a chain. For example if the processor <code>A</code> must
        /// process events before handler<code>B</code>:
        /// <code>dw.HandleEventsWith(A).Then(B);</code>
        /// </summary>
        /// <param name="processors">processors the event processors that will process events</param>
        /// <returns>a <see cref="ValueEventHandlerGroup{T}"/> that can be used to chain dependencies.</returns>
        public ValueEventHandlerGroup <T> HandleEventsWith(params IEventProcessor[] processors)
        {
            foreach (var processor in processors)
            {
                _consumerRepository.Add(processor);
            }

            var sequences = new ISequence[processors.Length];

            for (int i = 0; i < processors.Length; i++)
            {
                sequences[i] = processors[i].Sequence;
            }

            _ringBuffer.AddGatingSequences(sequences);

            return(new ValueEventHandlerGroup <T>(this, _consumerRepository, DisruptorUtil.GetSequencesFor(processors)));
        }
Пример #7
0
        private bool HasAvailableCapacity(ISequence[] gatingSequences, int requiredCapacity, long cursorValue)
        {
            var wrapPoint            = (cursorValue + requiredCapacity) - _bufferSize;
            var cachedGatingSequence = _gatingSequenceCache.Value;

            if (wrapPoint > cachedGatingSequence || cachedGatingSequence > cursorValue)
            {
                long minSequence = DisruptorUtil.GetMinimumSequence(gatingSequences, cursorValue);
                _gatingSequenceCache.SetValue(minSequence);

                if (wrapPoint > minSequence)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #8
0
        public MultiProducerSequencerRef1(int bufferSize, IWaitStrategy waitStrategy)
        {
            if (bufferSize < 1)
            {
                throw new ArgumentException("bufferSize must not be less than 1");
            }
            if (!bufferSize.IsPowerOf2())
            {
                throw new ArgumentException("bufferSize must be a power of 2");
            }

            _bufferSize             = bufferSize;
            _waitStrategy           = waitStrategy;
            _isBlockingWaitStrategy = !(waitStrategy is INonBlockingWaitStrategy);
            _availableBuffer        = new int[bufferSize];
            _indexMask  = bufferSize - 1;
            _indexShift = DisruptorUtil.Log2(bufferSize);

            InitialiseAvailableBuffer();
        }
Пример #9
0
        public void ShouldReturnNextPowerOfTwo()
        {
            var powerOfTwo = DisruptorUtil.CeilingNextPowerOfTwo(1000);

            Assert.AreEqual(1024, powerOfTwo);
        }
Пример #10
0
        public void ShouldReturnLongMaxWhenNoEventProcessors()
        {
            var sequences = new Sequence[0];

            Assert.AreEqual(long.MaxValue, DisruptorUtil.GetMinimumSequence(sequences));
        }
Пример #11
0
        public void ShouldReturnMinimumSequence()
        {
            var sequences = new[] { new Sequence(11), new Sequence(4), new Sequence(13) };

            Assert.AreEqual(4L, DisruptorUtil.GetMinimumSequence(sequences));
        }
Пример #12
0
 /// <summary>
 /// Create a group of event processors to be used as a dependency.
 /// </summary>
 /// <see cref="After(IValueEventHandler{T}[])"/>
 /// <param name="processors">processors the event processors, previously set up with <see cref="HandleEventsWith(IValueEventHandler{T}[])"/>,
 /// that will form the barrier for subsequent handlers or processors.</param>
 /// <returns>an <see cref="ValueEventHandlerGroup{T}"/> that can be used to setup a <see cref="ISequenceBarrier"/> over the specified event processors.</returns>
 public ValueEventHandlerGroup <T> After(params IEventProcessor[] processors)
 {
     return(new ValueEventHandlerGroup <T>(this, _consumerRepository, DisruptorUtil.GetSequencesFor(processors)));
 }
Пример #13
0
 /// <summary>
 /// <see cref="ISequencer.GetMinimumSequence"/>.
 /// </summary>
 public long GetMinimumSequence()
 {
     return(DisruptorUtil.GetMinimumSequence(Volatile.Read(ref _gatingSequences), _cursor.Value));
 }