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); }); }
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); }
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); }