Пример #1
0
        public override long GetRemainingCapacity()
        {
            long consumed = SequenceGroupManager.GetMinimumSequence(GatingSequences, Cursor.GetValue());
            long produced = Cursor.GetValue();

            return(BufferSize - (produced - consumed));
        }
        public override long Next(int n)
        {
            if (n < 1)
            {
                throw new ArgumentException($"{nameof(n)} must greater than 1.");
            }

            long nextValue = NextValue;

            long nextSequence         = nextValue + n;
            long wrapPoint            = nextSequence - BufferSize;
            long cachedGatingSequence = CachedValue;

            if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue)
            {
                Cursor.SetVolatileValue(nextValue);  // StoreLoad fence

                long minSequence;
                var  spinWait = default(AggressiveSpinWait);

                while (wrapPoint > (minSequence = SequenceGroupManager.GetMinimumSequence(GatingSequences, nextValue)))
                {
                    // Use waitStrategy to spin?
                    spinWait.SpinOnce();
                }

                CachedValue = minSequence;
            }

            NextValue = nextSequence;

            return(nextSequence);
        }
Пример #3
0
        /// <summary>
        /// Create a group of event processors to be used as a dependency.
        /// </summary>
        /// <param name="processors">the event processors, previously set up with <see cref="HandleEventsWith(Disruptor.IEventProcessor[]) "/>, that will form the barrier for subsequent handlers or processors.</param>
        /// <returns>an <see cref="EventHandlerGroup{T}"/> that can be used to setup a {@link SequenceBarrier} over the specified event processors.</returns>
        public EventHandlerGroup <T> After(params IEventProcessor[] processors)
        {
            foreach (var processor in processors)
            {
                _consumerRepository.Add(processor);
            }

            return(new EventHandlerGroup <T>(this, _consumerRepository, SequenceGroupManager.GetSequencesFor(processors)));
        }
        public override long GetRemainingCapacity()
        {
            long nextValue = CachedValue;

            long consumed = SequenceGroupManager.GetMinimumSequence(GatingSequences, nextValue);
            long produced = nextValue;

            return(BufferSize - (produced - consumed));
        }
Пример #5
0
        /// <summary>
        /// Wait for the <see cref="RingBuffer{TEvent}"/> to drain of published events then halt the workers.
        /// </summary>
        public void DrainAndHalt()
        {
            var workerSequences = GetWorkerSequences();

            while (_ringBuffer.GetCursor() > SequenceGroupManager.GetMinimumSequence(workerSequences))
            {
                Thread.Yield();
            }

            foreach (var processor in _workProcessors)
            {
                processor.Halt();
            }

            _started = 0;
        }
Пример #6
0
        private bool HasAvailableCapacity(ISequence[] gatingSequences, int requiredCapacity, long cursorValue)
        {
            long wrapPoint            = (cursorValue + requiredCapacity) - BufferSize;
            long cachedGatingSequence = _gatingSequenceCache.GetValue();

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

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

            return(true);
        }
Пример #7
0
        public override long Next(int n)
        {
            if (n < 1)
            {
                throw new ArgumentException($"{nameof(n)} must be > 0");
            }

            long next;
            long current;
            var  spinWait = default(AggressiveSpinWait);

            do
            {
                current = Cursor.GetValue();
                next    = current + n;

                var wrapPoint            = next - BufferSize;
                var cachedGatingSequence = _gatingSequenceCache.GetValue();

                if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current)
                {
                    var gatingSequence = SequenceGroupManager.GetMinimumSequence(GatingSequences, current);

                    if (wrapPoint > gatingSequence)
                    {
                        //should we spin based on the wait strategy?
                        spinWait.SpinOnce();
                        continue;
                    }

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

            return(next);
        }
Пример #8
0
        /// <summary>
        /// Set up custom event processors to handle events from the ring buffer. The Disruptor will automatically start these processors when <see cref="StartAsync"/> is called.
        /// </summary>
        /// <param name="processors">the event processors that will process events.</param>
        /// <returns>a <see cref="EventHandlerGroup{T}"/> that can be used to chain dependencies.</returns>
        public EventHandlerGroup <T> HandleEventsWith(params IEventProcessor[] processors)
        {
            if (processors == null)
            {
                return(null);
            }

            foreach (var processor in processors)
            {
                _consumerRepository.Add(processor);
            }

            var sequences = new ISequence[processors.Length];

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

            _ringBuffer.AddGatingSequences(sequences);
            return(new EventHandlerGroup <T>(this, _consumerRepository, SequenceGroupManager.GetSequencesFor(processors)));
        }
        private bool HasAvailableCapacity(int requiredCapacity, bool doStore)
        {
            var nextValue            = NextValue;
            var wrapPoint            = (nextValue + requiredCapacity) - BufferSize;
            var cachedGatingSequence = CachedValue;

            if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue)
            {
                if (doStore)
                {
                    Cursor.SetVolatileValue(nextValue);  // StoreLoad fence
                }

                long minSequence = SequenceGroupManager.GetMinimumSequence(GatingSequences, nextValue);
                CachedValue = minSequence;

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

            return(true);
        }
Пример #10
0
 public long GetMinimumSequence()
 {
     return(SequenceGroupManager.GetMinimumSequence(_sequences));
 }
Пример #11
0
 public bool Remove(ISequence sequence)
 {
     return(SequenceGroupManager.RemoveSequence(ref _sequences, sequence));
 }
Пример #12
0
 public void AddWhileRunning(ICursored cursored, ISequence sequence)
 {
     SequenceGroupManager.AddSequences(ref _sequences, cursored, sequence);
 }
Пример #13
0
 public virtual bool RemoveGatingSequence(ISequence sequence)
 {
     return(SequenceGroupManager.RemoveSequence(ref GatingSequences, sequence));
 }
Пример #14
0
 public virtual long GetMinimumSequence()
 {
     return(SequenceGroupManager.GetMinimumSequence(GatingSequences, Cursor.GetValue()));
 }
Пример #15
0
 public virtual void AddGatingSequences(params ISequence[] gatingSequences)
 {
     SequenceGroupManager.AddSequences(ref GatingSequences, this, gatingSequences);
 }