An ArraySegment{T} counterpart for unmanaged chunk of bytes.
Пример #1
0
        public void MessageHandler(int messageTypeId, ByteChunk chunk)
        {
            var hash = HashMessageId(messageTypeId);
            var actors = _messageMap[hash];

            for (var i = 0; i < _count; i++)
            {
                // invoke only if the mask matches the actors, to limit the overhead of calling unneeded actors
                if ((GetActorMask(i) & actors) != 0)
                {
                    _readers[i].MessageHandlerImpl(messageTypeId, chunk);
                }
            }
        }
Пример #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;
        }
Пример #3
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.Read(Arg.Is(Tail)).Returns(tailValue);

            var block = stackalloc byte[100];

            var chunk = new ByteChunk(block, length);
            Assert.IsTrue(_ringBuffer.Write(MessageTypeId, chunk));

            Received.InOrder(() =>
            {
                _buffer.Write(RingBufferDescriptor.EncodedMsgOffset(tailValue), chunk);
                _buffer.GetAtomicLong(tailValue);
                _atomicLong.VolatileWrite(CurrentSlot, RingBufferDescriptor.MakeHeader(recordLength, MessageTypeId));
                _atomicLong.VolatileWrite(Tail, tailValue + alignedRecordLength);
            });
        }
Пример #4
0
        public void ShouldRejectWriteWhenInsufficientSpace()
        {
            const int length = 200;
            const long head = 0;
            var tail = head +
                       (Capacity -
                        (length - RingBufferDescriptor.RecordAlignment).AlignToMultipleOf(
                            RingBufferDescriptor.RecordAlignment));

            _atomicLong.VolatileRead(Head).Returns(head);
            _atomicLong.Read(Tail).Returns(tail);

            var chunk = new ByteChunk(null, length);
            Assert.False(_ringBuffer.Write(MessageTypeId, chunk));

            _atomicInt.ReceivedWithAnyArgs(0);
            _atomicLong.DidNotReceiveWithAnyArgs().CompareExchange(IntPtr.Zero, 0, 0);
            _atomicLong.DidNotReceiveWithAnyArgs().VolatileWrite(IntPtr.Zero, 0);
            _buffer.DidNotReceiveWithAnyArgs().Write(0, new ByteChunk(null, 0));
        }
Пример #5
0
        public void ShouldInsertPaddingRecordPlusMessageOnBufferWrapWithHeadEqualToTail()
        {
            const int length = 200;
            var recordLength = length + RingBufferDescriptor.HeaderLength;
            var alignedRecordLength = recordLength.AlignToMultipleOf(RingBufferDescriptor.RecordAlignment);
            var tail = Capacity - RingBufferDescriptor.HeaderLength;
            var head = tail;

            _atomicLong.VolatileRead(Head).Returns(head);
            _atomicLong.Read(Tail).Returns(tail);

            var chunk = new ByteChunk(null, length);
            Assert.IsTrue(_ringBuffer.Write(MessageTypeId, chunk));

            Received.InOrder(() =>
            {
                // padding first
                _atomicLong.VolatileWrite(new IntPtr(tail),
                    RingBufferDescriptor.MakeHeader(RingBufferDescriptor.HeaderLength,
                        ManyToOneRingBuffer.PaddingMsgTypeId));

                // message then
                _buffer.Write(RingBufferDescriptor.EncodedMsgOffset(0), chunk);
                _atomicLong.VolatileWrite(new IntPtr(0), RingBufferDescriptor.MakeHeader(recordLength, MessageTypeId));
                _atomicLong.VolatileWrite(Tail, tail + alignedRecordLength + RingBufferDescriptor.HeaderLength);
            });
        }
Пример #6
0
 public bool Equals(ByteChunk other)
 {
     return(Pointer == other.Pointer && Length == other.Length);
 }
Пример #7
0
 public void Write(ByteChunk chunk)
 {
     var slice = new ByteSlice(chunk);
     WriteImpl(ref slice);
 }
Пример #8
0
        public int Read(ByteChunk chunk)
        {
            var slice = new ByteSlice(chunk);

            return(ReadImpl(ref slice));
        }
Пример #9
0
        // ReSharper disable once UnusedParameter.Local

        private void ValidateLength(ByteChunk chunk)
        {
            if (chunk.Length > MaximumMessageLength)
            {
                throw new ArgumentException("");
            }
        }
Пример #10
0
 public int Read(ByteChunk chunk)
 {
     var slice = new ByteSlice(chunk);
     return ReadImpl(ref slice);
 }
Пример #11
0
 public void Write(int offset, ByteChunk chunk)
 {
     Native.MemcpyUnmanaged(RawBytes + offset, chunk.Pointer, chunk.Length);
 }
Пример #12
0
 public void Write(int offset, ByteChunk chunk)
 {
     Native.MemcpyUnmanaged(RawBytes + offset, chunk.Pointer, chunk.Length);
 }
Пример #13
0
        public void ShouldInsertPaddingRecordPlusMessageOnBufferWrap()
        {
            const int length = 200;
            var recordLength = length + RingBufferDescriptor.HeaderLength;
            var alignedRecordLength = recordLength.AlignToMultipleOf(RingBufferDescriptor.RecordAlignment);
            long tail = Capacity - RingBufferDescriptor.HeaderLength;
            var head = tail - RingBufferDescriptor.RecordAlignment*4;

            _atomicLong.VolatileRead(Head).Returns(head);
            _atomicLong.VolatileRead(Tail).Returns(tail);
            _atomicLong.CompareExchange(Tail, tail + alignedRecordLength + RingBufferDescriptor.RecordAlignment, tail)
                .Returns(tail);

            var chunk = new ByteChunk(null, length);
            Assert.True(_ringBuffer.Write(MessageTypeId, chunk));

            Received.InOrder(() =>
            {
                // padding first
                _atomicLong.VolatileWrite(new IntPtr(tail),
                    RingBufferDescriptor.MakeHeader(RingBufferDescriptor.HeaderLength,
                        ManyToOneRingBuffer.PaddingMsgTypeId));

                // then write from the start
                _atomicLong.VolatileWrite(new IntPtr(0), RingBufferDescriptor.MakeHeader(-recordLength, MessageTypeId));
                _buffer.Write(RingBufferDescriptor.EncodedMsgOffset(0), chunk);
                _buffer.GetAtomicInt(0);
                _atomicInt.VolatileWrite(new IntPtr(0), recordLength);
            });
        }
Пример #14
0
        public void Write(ByteChunk chunk)
        {
            var slice = new ByteSlice(chunk);

            WriteImpl(ref slice);
        }
Пример #15
0
 public bool Equals(ByteChunk other)
 {
     return Pointer == other.Pointer && Length == other.Length;
 }
Пример #16
0
 public static unsafe Envelope T(ByteChunk ch)
 {
     return *((Envelope*) (ch.Pointer + 2));
 }
Пример #17
0
 public void MessageHandlerImpl(int messageTypeId, ByteChunk chunk)
 {
     _reader(this, messageTypeId, chunk);
 }
Пример #18
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;
        }