示例#1
0
        /* ---- many producers ---- */

        public override void Produce(T t)
        {
            if (_size == 0)
            {
                return;
            }

            long            produceNumber = _produceCount.AndIncrement;
            int             offset        = ( int )(produceNumber & _mask);
            VolatileRef <T> volatileRef   = _data[offset];

            if (AssertPreviousCompleted(produceNumber, volatileRef))
            {
                volatileRef.Ref           = t;
                volatileRef.ProduceNumber = produceNumber;
            }
            else
            {
                // If we don't manage to wait for the previous produce to complete even after
                // all the yields in `assertPreviousCompleted`, we drop `t` to avoid causing
                // a problem in db operation. We increment dropEvents to so the RecentBuffer
                // consumer can detect that there has been a drop.
                _dropEvents.incrementAndGet();
            }
        }
示例#2
0
        public override void Foreach(System.Action <T> consumer)
        {
            if (_size == 0)
            {
                return;
            }

            long snapshotProduce = _produceCount.get();
            long snapshotConsume = Math.Max(_consumeCount.get(), snapshotProduce - _size);

            for (long i = snapshotConsume; i < snapshotProduce; i++)
            {
                int             offset      = ( int )(i & _mask);
                VolatileRef <T> volatileRef = _data[offset];
                if (volatileRef.ProduceNumber < i)
                {
                    return;
                }
                consumer(volatileRef.Ref);
            }
        }
示例#3
0
        public RingRecentBuffer(int size)
        {
            if (size > 0)
            {
                Preconditions.requirePowerOfTwo(size);
            }

            this._size = size;
            _mask      = size - 1;

            //noinspection unchecked
            _data = new VolatileRef[size];
            for (int i = 0; i < size; i++)
            {
                _data[i] = new VolatileRef <T>();
                _data[i].produceNumber = i - size;
            }

            _produceCount = new AtomicLong(0);
            _consumeCount = new AtomicLong(0);
            _dropEvents   = new AtomicLong(0);
        }
示例#4
0
        private bool AssertPreviousCompleted(long produceNumber, VolatileRef <T> volatileRef)
        {
            int  attempts          = 100;
            long prevProduceNumber = volatileRef.ProduceNumber;

            while (prevProduceNumber != produceNumber - _size && attempts > 0)
            {
                // Coming in here is expected to be very rare, because it means that producers have
                // circled around the ring buffer, and the producer `size` elements ago hasn't finished
                // writing to the buffer. We yield and hope the previous produce is done when we get back.
                try
                {
                    Thread.Sleep(0, 1000);
                }
                catch (InterruptedException)
                {
                    // continue
                }
                prevProduceNumber = volatileRef.ProduceNumber;
                attempts--;
            }
            return(attempts > 0);
        }