public RingMemoryPage[] GetPages(long offset, long count)
        {
            VerifyNotDisposed();

            Require.That(count > 0, "Count must be greater than zero", "count");

            VerifyCapacityRange(offset, offset + count);

            long startPage = GetPage(offset);
            long endPage = GetPage(offset + count - 1);

            var result = new RingMemoryPage[endPage - startPage + 1];

            for (long i = startPage; i <= endPage; i++)
            {
                long pageOffset =
                    i == startPage
                    ? offset - GetPageOffset(i)
                    : 0;

                long pageCount =
                    i == endPage
                    ? (offset + count) - GetPageOffset(i)
                    : BlockSize - pageOffset;

                result[i] = new RingMemoryPage(_pages[i - _pagesOffset], (int)pageOffset, (int)pageCount);
            }

            return result;
        }
        /// <summary>
        /// Gets a reference to the backing memory pages based on the provided
        /// offset and count.
        /// </summary>
        /// <remarks>
        /// <see cref="GetPages"/> provides access to the backing pages of the
        /// stream. Reading from or writing to the stream, this method is preferred
        /// over <see cref="Read"/> because working with the backing pages limits
        /// the number of extra memory allocations that need to be made.
        /// </remarks>
        /// <param name="offset">The start offset for which to get the backing pages</param>
        /// <param name="count">The number of bytes the returned pages must span</param>
        /// <returns>The memory pages describing the requested range</returns>
        public RingMemoryPage[] GetPages(long offset, long count)
        {
            VerifyNotDisposed();

            Require.That(count > 0, "Count must be greater than zero", "count");

            VerifyCapacityRange(offset, offset + count);

            // Calculate the complete range of pages based on the data that
            // is being read.

            long startPage = GetPage(offset);
            long endPage = GetPage(offset + count - 1);

            var result = new RingMemoryPage[endPage - startPage + 1];

            // For all returned memory pages, calculate the offset and count
            // for each separate page and return this including a reference to
            // the backing memory for that page.

            for (long i = startPage; i <= endPage; i++)
            {
                long pageOffset =
                    i == startPage
                    ? offset - GetPageOffset(i)
                    : 0;

                long pageCount =
                    i == endPage
                    ? (offset + count) - GetPageOffset(i)
                    : BlockSize - pageOffset;

                result[i] = new RingMemoryPage(_pages[i - _pagesOffset], (int)pageOffset, (int)pageCount);
            }

            return result;
        }
Example #3
0
        private bool TryGetSendPage(out RingMemoryPage page)
        {
            long pageSize = Math.Min(
                _sendStream.BlockSize - _sendStream.Head % _sendStream.BlockSize, // Maximum size to stay on the page
                _sendStream.Length - _sendStream.Head // Maximum size to send at all
            );

            if (pageSize == 0)
            {
                page = new RingMemoryPage();

                return false;
            }
            else
            {
                page = _sendStream.GetPage(_sendStream.Head, pageSize);

                Debug.Assert(_sendStream.Head + pageSize <= _sendStream.Length);

                return true;
            }
        }