GSF.IO.Unmanaged.MemoryPoolPageList.TryGetNextPage C# (CSharp) Method

TryGetNextPage() public method

Requests a new block from the buffer pool.
Thrown if the list is full
public TryGetNextPage ( int &index, IntPtr &addressPointer ) : bool
index int the index identifier of the block
addressPointer System.IntPtr the address to the start of the block
return bool
        public bool TryGetNextPage(out int index, out IntPtr addressPointer)
        {
            lock (m_syncRoot)
            {
                if (m_disposed)
                    throw new ObjectDisposedException(GetType().FullName);

                index = m_isPageFree.FindSetBit();
                if (index < 0)
                {
                    index = -1;
                    addressPointer = IntPtr.Zero;
                    return false;
                }

                m_usedPageCount++;
                m_isPageFree.ClearBit(index);

                int allocationIndex = index >> m_pagesPerMemoryBlockShiftBits;
                int blockOffset = index & m_pagesPerMemoryBlockMask;
                Memory block = m_memoryBlocks[allocationIndex];
                if (block == null)
                {
                    Log.Publish(MessageLevel.Warning, MessageFlags.BugReport, "Memory Block inside Memory Pool is null. Possible race condition.");
                    throw new NullReferenceException("Memory Block is null");
                }
                if (block.Address == IntPtr.Zero)
                {
                    Log.Publish(MessageLevel.Warning, MessageFlags.BugReport, "Memory Block inside Memory Pool was released prematurely. Possible race condition.");
                    throw new NullReferenceException("Memory Block is null");
                }

                addressPointer = block.Address + blockOffset * PageSize;

                index++;
                return true;
            }
        }

Usage Example

Example #1
0
        /// <summary>
        /// Requests a page from the buffered pool.
        /// If there is not a free one available, method will block
        /// and request a collection of unused pages by raising
        /// <see cref="RequestCollection"/> event.
        /// </summary>
        /// <param name="index">the index id of the page that was allocated</param>
        /// <param name="addressPointer"> outputs a address that can be used
        /// to access this memory address.  You cannot call release with this parameter.
        /// Use the returned index to release pages.</param>
        /// <remarks>
        /// IMPORTANT NOTICE: Be careful when calling this method as the calling thread
        /// will block if no memory is available to have a background collection to occur.
        ///
        /// There is a possiblity for a deadlock if calling this method from within a lock.
        ///
        /// The page allocated will not be initialized,
        /// so assume that the data is garbage.</remarks>
        public void AllocatePage(out int index, out IntPtr addressPointer)
        {
            if (m_pageList.TryGetNextPage(out index, out addressPointer))
            {
                return;
            }

            lock (m_syncAllocate)
            {
                //m_releasePageVersion is approximately the number of times that a release page function has been called.
                //                     due to race conditions, the number may not be exact, but it will have at least changed.

                while (true)
                {
                    int releasePageVersion = m_releasePageVersion;
                    if (m_pageList.TryGetNextPage(out index, out addressPointer))
                    {
                        return;
                    }

                    RequestMoreFreeBlocks();
                    if (releasePageVersion == m_releasePageVersion)
                    {
                        Log.Publish(MessageLevel.Critical, MessageFlags.PerformanceIssue, "Out Of Memory", string.Format("Memory pool has run out of memory: Current Usage: {0}MB", CurrentCapacity / 1024 / 1024));
                        throw new OutOfMemoryException("Memory pool is full");
                    }

                    //Due to a race condition, it is possible that someone else get the freed block
                    //and we must request freeing again.
                }
            }
        }