Example #1
0
        public void ShouldWriteToEmptyBuffer()
        {
            const int length              = 8;
            var       recordLength        = length + RingBufferDescriptor.HeaderLength;
            var       alignedRecordLength = recordLength.AlignToMultipleOf(RingBufferDescriptor.RecordAlignment);

            const int headValue = 0;

            _atomicLong.VolatileRead(Arg.Is(Head)).Returns(headValue);
            const int tailValue = 0;

            _atomicLong.VolatileRead(Arg.Is(Tail)).Returns(tailValue);

            _atomicLong.CompareExchange(Arg.Is(Tail), Arg.Is(tailValue), Arg.Is(tailValue + alignedRecordLength))
            .Returns(tailValue);

            var block = stackalloc byte[100];

            var chunk = new ByteChunk(block, length);

            Assert.IsTrue(_ringBuffer.Write(MessageTypeId, chunk));

            Received.InOrder(() =>
            {
                _atomicLong.VolatileWrite(CurrentSlot, RingBufferDescriptor.MakeHeader(-recordLength, MessageTypeId));
                _buffer.Write(RingBufferDescriptor.EncodedMsgOffset(tailValue), chunk);
                _buffer.GetAtomicInt(tailValue);
                _atomicInt.VolatileWrite(CurrentSlot, recordLength);
            });
        }
Example #2
0
        public bool Write(int messageTypeId, ByteChunk chunk)
        {
            ValidateMessageTypeId(messageTypeId);
            ValidateLength(chunk);

            var isSuccessful = false;

            var recordLength     = chunk.Length + HeaderLength;
            var requiredCapacity = recordLength.AlignToMultipleOf(RecordAlignment);
            var recordIndex      = ClaimCapacity(requiredCapacity);

            if (InsufficientCapacity != recordIndex)
            {
                var index = _buffer.GetAtomicLong(recordIndex);
                index.VolatileWrite(MakeHeader(-recordLength, messageTypeId));
                var offset = EncodedMsgOffset(recordIndex);
                _buffer.Write(offset, chunk);
                _buffer.GetAtomicInt(recordIndex).VolatileWrite(recordLength);

                isSuccessful = true;
            }

            return(isSuccessful);
        }
Example #3
0
        public bool Write(int messageTypeId, ByteChunk chunk)
        {
            ValidateMessageTypeId(messageTypeId);
            ValidateLength(chunk);

            var recordLength     = chunk.Length + HeaderLength;
            var requiredCapacity = recordLength.AlignToMultipleOf(RecordAlignment);

            var head = _headCache.Read();
            var tail = _tail.Read();
            var availableCapacity = Capacity - (int)(tail - head);

            if (requiredCapacity > availableCapacity)
            {
                head = _head.VolatileRead();

                if (requiredCapacity > Capacity - (int)(tail - head))
                {
                    return(false);
                }

                _headCache.Write(head);
            }

            var padding           = 0;
            var recordIndex       = (int)tail & _mask;
            var toBufferEndLength = Capacity - recordIndex;

            if (requiredCapacity > toBufferEndLength)
            {
                var headIndex = (int)head & _mask;

                if (requiredCapacity > headIndex)
                {
                    head      = _head.VolatileRead();
                    headIndex = (int)head & _mask;
                    if (requiredCapacity > headIndex)
                    {
                        return(false);
                    }

                    _headCache.Write(head);
                }

                padding = toBufferEndLength;
            }

            if (0 != padding)
            {
                var tailAtomic = _buffer.GetAtomicLong(recordIndex);
                tailAtomic.VolatileWrite(MakeHeader(padding, PaddingMsgTypeId));
                recordIndex = 0;
            }

            var offset = EncodedMsgOffset(recordIndex);

            _buffer.Write(offset, chunk);

            var index = _buffer.GetAtomicLong(recordIndex);

            index.VolatileWrite(MakeHeader(recordLength, messageTypeId));

            _tail.VolatileWrite(tail + requiredCapacity + padding);

            return(true);
        }