Example #1
0
        public void should_acquire_and_release_from_multiple_threads()
        {
            // Arrange
            using (var bufferManager = RioBufferManager.Allocate(128, 64))
            {
                // Act
                var tasks = new Task[6];
                for (var i = 0; i < tasks.Length; i++)
                {
                    tasks[i] = Task.Run(() =>
                    {
                        for (var j = 0; j < 50 * 1000; j++)
                        {
                            var buffers = new RioBuffer[10];
                            for (var k = 0; k < buffers.Length; k++)
                            {
                                buffers[k] = bufferManager.AcquireBuffer(TimeSpan.FromMilliseconds(100));
                            }

                            for (var k = 0; k < buffers.Length; k++)
                            {
                                bufferManager.ReleaseBuffer(buffers[k]);
                            }
                        }
                    });
                }

                // Assert
                var allTaskAreCompleted = Task.WaitAll(tasks, TimeSpan.FromSeconds(3));
                Assert.IsTrue(allTaskAreCompleted);
            }
        }
Example #2
0
 public void Reset()
 {
     _remainingFrameByteCount     = ByteCount.Empty;
     _currentRegisteredSegmentEnd = (byte *)0;
     _currentBuffer = null;
     _currentFrame.Clear();
     _pendingBuffers.Clear();
 }
Example #3
0
        private int ReadFrom(RioBuffer buffer)
        {
            if (buffer.Length < sizeof(int))
            {
                throw new ArgumentException("buffer is too small", nameof(buffer));
            }

            return(*(int *)buffer.Data);
        }
Example #4
0
        private void WriteTo(RioBuffer buffer, int value)
        {
            if (buffer.Length < sizeof(int))
            {
                throw new ArgumentException("buffer is too small", nameof(buffer));
            }

            *(int *)buffer.Data = value;
        }
Example #5
0
        public unsafe void Send(RioBuffer buffer)
        {
            var requestContextKey = new RioRequestContextKey(buffer.Id, RioRequestType.Send);

            if (!WinSock.Extensions.Send(_handle, buffer.BufferDescriptor, 1, RIO_SEND_FLAGS.NONE, requestContextKey.ToRioRequestCorrelationId()))
            {
                WinSock.ThrowLastWsaError();
            }
        }
Example #6
0
        private void OnReceiveComplete(RioBuffer buffer)
        {
            var receivingContext = _threadLocalReceivingContext.Value;

            List <BufferSegment> framedMessage;

            while (_messageFramer.TryFrameNextMessage(buffer, out framedMessage))
            {
                var releasableMessage = _serializationEngine.DeserializeWithLengthPrefix(framedMessage, receivingContext.BinaryReader);
                try
                {
                    MessageReceived(this, releasableMessage.MessageTypeId, releasableMessage.Message);
                }
                catch (Exception ex)
                {
                    MessageHandlingFailed(this, releasableMessage.MessageTypeId, releasableMessage.Message, ex);
                }
                finally
                {
                    releasableMessage.Releaser?.Release(releasableMessage.Message);
                }
            }
        }
Example #7
0
        private static List <RioBuffer> CreateBuffers(byte *buffer, RIO_BUF *segmentBuffer, int maxLength, int segmentLength = 10)
        {
            var segments       = new List <RioBuffer>();
            var pBuffer        = buffer;
            var readDataLength = 0;
            var segmentId      = 0;

            while (readDataLength != maxLength)
            {
                var dataLength = Math.Min(segmentLength, maxLength - readDataLength);

                segmentBuffer->Length = dataLength;
                var segment = new RioBuffer(segmentId++, pBuffer, segmentBuffer, segmentLength)
                {
                    DataLength = dataLength
                };
                segments.Add(segment);
                readDataLength += dataLength;
                pBuffer        += segmentLength;
                segmentBuffer++;
            }
            return(segments);
        }
Example #8
0
        public bool TryFrameNextMessage(RioBuffer rioBuffer, out List <BufferSegment> frame)
        {
            frame = null;

            var currentSegmentIsCompleted = _currentRegisteredSegmentEnd == _currentBufferSegment.Data;

            if (_remainingFrameByteCount.IsEmpty)
            {
                // the previous frame was framed entirely, we can reset it
                _currentFrame.Clear();

                // we can release all pending buffers, but the current one must be kept if it is not entirely read
                ReleasePendingBuffers(currentSegmentIsCompleted);

                if (currentSegmentIsCompleted && _currentBuffer != null)
                {
                    _currentRegisteredSegmentEnd = rioBuffer.Data;
                    return(false);
                }
            }

            if (rioBuffer != _currentBuffer)
            {
                // a new buffer is submitted, we initialize a new frame segment
                _currentBufferSegment = new BufferSegment(rioBuffer.Data);
                _currentBuffer        = rioBuffer;
                _pendingBuffers.Add(_currentBuffer);
            }

            _currentRegisteredSegmentEnd = rioBuffer.Data + rioBuffer.DataLength;

            // we need to read the length prefix of the frame, so we loop until we have the 4 bytes of data we need
            while (!_remainingFrameByteCount.IsComplete)
            {
                if (_currentBufferSegment.Data >= _currentRegisteredSegmentEnd)
                {
                    return(false);
                }

                _remainingFrameByteCount.Push(_currentBufferSegment.Data);
                _currentBufferSegment = new BufferSegment(_currentBufferSegment.Data + 1, _currentBufferSegment.Length);
            }

            // we just finished to read the frame length and the buffer is completed, we can release it right away
            if (_currentFrame.Count == 0)
            {
                ReleasePendingBuffers(_currentBufferSegment.Data == _currentRegisteredSegmentEnd);
            }

            // at this point, we know the actual frame length
            // if the frame bytes span beyond the end of the current buffer, we trim the current frame part
            // to the end of the buffer and we return so that we can be provided another buffer
            var frameEnd = _currentBufferSegment.Data + _remainingFrameByteCount.Value;

            if (frameEnd > _currentRegisteredSegmentEnd)
            {
                var segmentLength = _currentBufferSegment.Length + (int)(_currentRegisteredSegmentEnd - _currentBufferSegment.Data);
                _currentBufferSegment           = new BufferSegment(_currentBufferSegment.Data, segmentLength);
                _remainingFrameByteCount.Value -= _currentBufferSegment.Length;
                _currentFrame.Add(_currentBufferSegment);
                return(false);
            }

            // if the buffer contains enough data, we take as much as we need and mark the frame as completed
            _currentBufferSegment = new BufferSegment(_currentBufferSegment.Data, _currentBufferSegment.Length + _remainingFrameByteCount.Value);
            _currentFrame.Add(_currentBufferSegment);

            _currentBufferSegment    = new BufferSegment(_currentBufferSegment.Data + _currentBufferSegment.Length);
            _remainingFrameByteCount = ByteCount.Empty;

            frame = _currentFrame;
            return(true);
        }
Example #9
0
 public void ReleaseBuffer(RioBuffer buffer)
 {
     LastReleasedSegmentId = buffer.Id > LastReleasedSegmentId ? buffer.Id : LastReleasedSegmentId;
 }