This class allocates and pools unmanaged memory. Designed to be internally thread safe.
Be careful how this class is referenced. Deadlocks can occur when registering to event RequestCollection and when calling AllocatePage. See comments for these methods for considerations.
Inheritance: IDisposable
        /// <summary>
        /// Creates a new instance of <see cref="PageReplacementAlgorithm"/>.
        /// </summary>
        /// <param name="pool">The memory pool that blocks will be allocated from.</param>
        public PageReplacementAlgorithm(MemoryPool pool)
        {
            if (pool.PageSize < 4096)
                throw new ArgumentOutOfRangeException("PageSize Must be greater than 4096", "pool");
            if (!BitMath.IsPowerOfTwo(pool.PageSize))
                throw new ArgumentException("PageSize Must be a power of 2", "pool");

            m_maxValidPosition = (int.MaxValue - 1) * (long)pool.PageSize; //Max position 

            m_syncRoot = new object();
            m_memoryPageSizeMask = pool.PageSize - 1;
            m_memoryPageSizeShiftBits = BitMath.CountBitsSet((uint)m_memoryPageSizeMask);
            m_pageList = new PageList(pool);
            m_arrayIndexLocks = new WeakList<PageLock>();
        }
 /// <summary>
 /// Creates a <see cref="DiskMedium"/> from a <see cref="stream"/>. 
 /// This will read the existing header from the <see cref="stream"/>.
 /// </summary>
 /// <param name="stream">An open <see cref="FileStream"/> to use. The <see cref="DiskMedium"/>
 /// will assume ownership of this <see cref="FileStream"/>.</param>
 /// <param name="pool">The <see cref="MemoryPool"/> to allocate data from.</param>
 /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
 /// <returns></returns>
 public static DiskMedium OpenFile(CustomFileStream stream, MemoryPool pool, int fileStructureBlockSize)
 {
     byte[] buffer = new byte[fileStructureBlockSize];
     stream.ReadRaw(0, buffer, fileStructureBlockSize);
     FileHeaderBlock header = FileHeaderBlock.Open(buffer);
     BufferedFile disk = new BufferedFile(stream, pool, header, isNewFile: false);
     return new DiskMedium(disk, header);
 }
        /// <summary>
        /// Creates a <see cref="DiskMedium"/> from a <see cref="stream"/>. 
        /// This will initialize the <see cref="stream"/> as an empty file structure.
        /// </summary>
        /// <param name="stream">An open <see cref="FileStream"/> to use. The <see cref="DiskMedium"/>
        ///     will assume ownership of this <see cref="FileStream"/>.</param>
        /// <param name="pool">the <see cref="MemoryPool"/> to allocate data from</param>
        /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
        /// <param name="flags">Flags to write to the file</param>
        /// <returns></returns>
        /// <remarks>
        /// This will not check if the file is truely a new file. If calling this with an existing
        /// archive file, it will overwrite the table of contents, corrupting the file.
        /// </remarks>
        public static DiskMedium CreateFile(CustomFileStream stream, MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
        {
            FileHeaderBlock header = FileHeaderBlock.CreateNew(fileStructureBlockSize, flags);

            BufferedFile disk = new BufferedFile(stream, pool, header, isNewFile: true);
            return new DiskMedium(disk, header);
        }
 /// <summary>
 /// Creates a <see cref="DiskMedium"/> that is entirely based in memory.
 /// </summary>
 /// <param name="pool">the <see cref="MemoryPool"/> to allocate data from</param>
 /// <param name="fileStructureBlockSize">the block size of the file structure. Usually 4kb.</param>
 /// <param name="flags">Flags to write to the file</param>
 /// <returns></returns>
 public static DiskMedium CreateMemoryFile(MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
 {
     FileHeaderBlock header = FileHeaderBlock.CreateNew(fileStructureBlockSize, flags);
     MemoryPoolFile disk = new MemoryPoolFile(pool);
     return new DiskMedium(disk, header);
 }
 /// <summary>
 /// Creates a new PageMetaDataList.
 /// </summary>
 /// <param name="memoryPool">The buffer pool to utilize if any unmanaged memory needs to be created.</param>
 public PageList(MemoryPool memoryPool)
 {
     m_memoryPool = memoryPool;
     m_listOfPages = new NullableLargeArray<InternalPageMetaData>();
     m_pageIndexLookupByPositionIndex = new SortedList<int, int>();
 }
 /// <summary>
 /// Creates a <see cref="BinaryStream"/> that is in memory only.
 /// </summary>
 public BinaryStream(MemoryPool pool)
     : this(new MemoryPoolStream(pool), false)
 {
     if (!BitConverter.IsLittleEndian)
         throw new Exception("Only designed to run on a little endian processor.");
 }
 /// <summary>
 /// Create a new <see cref="MemoryPoolStream"/>
 /// </summary>
 public MemoryPoolStream(MemoryPool pool)
     : base(pool)
 {
     m_blockSize = pool.PageSize;
 }
 static Globals()
 {
     MemoryPool = new MemoryPool(65536);
 }
 public static DiskIo OpenFile(string fileName, MemoryPool pool, bool isReadOnly)
 {
     int fileStructureBlockSize;
     CustomFileStream fileStream = CustomFileStream.OpenFile(fileName, pool.PageSize, out fileStructureBlockSize, isReadOnly, true);
     DiskMedium disk = DiskMedium.OpenFile(fileStream, pool, fileStructureBlockSize);
     return new DiskIo(disk, isReadOnly);
 }
 public static DiskIo CreateFile(string fileName, MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
 {
     //Exclusive opening to prevent duplicate opening.
     CustomFileStream fileStream = CustomFileStream.CreateFile(fileName, pool.PageSize, fileStructureBlockSize);
     DiskMedium disk = DiskMedium.CreateFile(fileStream, pool, fileStructureBlockSize, flags);
     return new DiskIo(disk, false);
 }
 public static DiskIo CreateMemoryFile(MemoryPool pool, int fileStructureBlockSize, params Guid[] flags)
 {
     DiskMedium disk = DiskMedium.CreateMemoryFile(pool, fileStructureBlockSize, flags);
     return new DiskIo(disk, false);
 }
 /// <summary>
 /// Create a new <see cref="MemoryPoolStream"/>
 /// </summary>
 public MemoryPoolStream(MemoryPool pool)
     : base(pool)
 {
     m_blockSize = pool.PageSize;
 }
 /// <summary>
 /// Releases the unmanaged resources used by the <see cref="MemoryFile"/> object and optionally releases the managed resources.
 /// </summary>
 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
 private void Dispose(bool disposing)
 {
     if (!m_disposed)
     {
         try
         {
             if (!m_pool.IsDisposed)
             {
                 m_pool.ReleasePages(m_settings.GetAllPageIndexes());
             }
         }
         finally
         {
             m_pool = null;
             m_settings = null;
             m_disposed = true;
         }
     }
 }
 /// <summary>
 /// Create a new <see cref="MemoryPoolStreamCore"/>
 /// </summary>
 public MemoryPoolStreamCore(MemoryPool pool)
 {
     m_pool = pool;
     m_shiftLength = pool.PageShiftBits;
     m_pageSize = pool.PageSize;
     m_invertMask = ~(long)(pool.PageSize - 1);
     m_settings = new Settings();
     m_syncRoot = new object();
 }
        /// <summary>
        /// Creates a file backed memory stream.
        /// </summary>
        /// <param name="stream">The <see cref="CustomFileStream"/> to buffer</param>
        /// <param name="pool">The <see cref="MemoryPool"/> to allocate memory from</param>
        /// <param name="header">The <see cref="FileHeaderBlock"/> to be managed when modifications occur</param>
        /// <param name="isNewFile">Tells if this is a newly created file. This will make sure that the 
        /// first 10 pages have the header data copied to it.</param>
        public BufferedFile(CustomFileStream stream, MemoryPool pool, FileHeaderBlock header, bool isNewFile)
        {
            m_fileStructureBlockSize = header.BlockSize;
            m_diskBlockSize = pool.PageSize;
            m_lengthOfHeader = header.BlockSize * header.HeaderBlockCount;
            m_writeBuffer = new MemoryPoolStreamCore(pool);
            m_pool = pool;
            m_queue = stream;
            m_syncRoot = new object();
            m_pageReplacementAlgorithm = new PageReplacementAlgorithm(pool);
            pool.RequestCollection += m_pool_RequestCollection;

            if (isNewFile)
            {
                byte[] headerBytes = header.GetBytes();
                for (int x = 0; x < header.HeaderBlockCount; x++)
                {
                    m_queue.WriteRaw(0, headerBytes, headerBytes.Length);
                }
            }
            m_lengthOfCommittedData = (header.LastAllocatedBlock + 1) * (long)header.BlockSize;
            m_writeBuffer.ConfigureAlignment(m_lengthOfCommittedData, pool.PageSize);
        }
 /// <summary>
 /// Create a new <see cref="MemoryPoolFile"/>
 /// </summary>
 public MemoryPoolFile(MemoryPool pool)
     : base(pool)
 {
     m_ioSession = new IoSession(this);
     m_isReadOnly = false;
 }