示例#1
0
        public void TryAllocateTest()
        {
            IMemorySlab target = CreateIMemorySlab();

            //allocate 1 byte
            long         smallLength    = 1;
            IMemoryBlock allocatedBlock = null;
            bool         result1        = target.TryAllocate(smallLength, out allocatedBlock);

            Assert.AreEqual <long>(smallLength, allocatedBlock.Length);
            Assert.AreEqual <long>(0, allocatedBlock.StartLocation);
            Assert.AreEqual <bool>(true, result1);

            //allocate rest of slab
            long         restLength      = totalSize - 1;
            IMemoryBlock allocatedBlock2 = null;
            bool         result2         = target.TryAllocate(restLength, out allocatedBlock2);

            Assert.AreEqual <long>(restLength, allocatedBlock2.Length);
            Assert.AreEqual <long>(1, allocatedBlock2.StartLocation);
            Assert.AreEqual <bool>(true, result2);

            //Now try to allocate another byte and expect it to fail
            IMemoryBlock allocatedBlock3 = null;
            bool         result3         = target.TryAllocate(smallLength, out allocatedBlock3);

            Assert.AreEqual <bool>(false, result3);

            //Clean up
            target.Free(allocatedBlock);
            target.Free(allocatedBlock2);
        }
示例#2
0
 public MBC3Cartridge(byte[] romData)
 {
     _romData = romData;
     _ramData = new byte[32768];
     ROM      = new LambdaMemoryBlock(32768, ReadRom, WriteRom);
     RAM      = new LambdaMemoryBlock(8192, ReadRam, WriteRam);
 }
示例#3
0
        public MemoryWindow([NotNull] IMemoryBlock memoryBlock, int offset, long size)
        {
            if (memoryBlock == null)
            {
                throw new ArgumentNullException(nameof(memoryBlock));
            }

            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }

            if (size > memoryBlock.Size - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size), "The window size is larger than the size of the target block.");
            }

            Pointer = memoryBlock.GetPointer() + offset;
            Size    = size;

            mReadable = memoryBlock is IReadableMemory;
            mWritable = memoryBlock is IWritableMemory;

            if (!mReadable && !mWritable)
            {
                // neither readable nor writable!? must be some unknown memory restriction...
                mReadable = mWritable = true;
            }
        }
示例#4
0
        public static Bitmap RenderTile(IMemoryBlock vram, int tileIndex)
        {
            if (tileIndex < 0 || tileIndex >= 384)
            {
                throw new ArgumentException("Invalid tile index.", nameof(tileIndex));
            }

            var shades = new[]
            {
                new Pixel(255, 255, 255),
                new Pixel(192, 192, 192),
                new Pixel(96, 96, 96),
                new Pixel(0, 0, 0),
            };

            var tile = new Bitmap(8, 8);

            var tileOffset = tileIndex << 4;

            for (int y = 0; y < 8; y++)
            {
                var lower = vram[tileOffset + y * 2];
                var upper = vram[tileOffset + y * 2 + 1];

                for (int x = 0; x < 8; x++)
                {
                    var shadeId = (upper.GetBit(7 - x) ? 2 : 0) + (lower.GetBit(7 - x) ? 1 : 0);
                    var shade   = shades[shadeId];

                    tile[x, y] = shade;
                }
            }

            return(tile);
        }
示例#5
0
 public RomOnlyCartridge(byte[] romData)
 {
     Debug.Assert(romData.Length == 32768);
     ROM = new MemoryBlock(romData);
     // TODO apparently some small carts DO have a (non-switchable) RAM
     RAM = new MemorySink();
 }
示例#6
0
        public TextureView([NotNull] IMemoryBlock memory, int stride, TextureFormat format)
        {
            if (memory == null)
            {
                throw new ArgumentNullException(nameof(memory));
            }

            if (stride <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(stride));
            }

            mMemory         = memory;
            mFormat         = format;
            mReadableMemory = new ReadOnlyMemoryWindow(memory);

            mStride = stride;
            mWidth  = stride >> 2;
            mHeight = (int)(memory.Size / stride);

            mReadable = memory is IReadableMemory;
            mWritable = memory is IWritableMemory;

            if (!mReadable && !mWritable)
            {
                // neither readable nor writable!? must be some unknown memory restriction...
                mReadable = mWritable = true;
            }
        }
示例#7
0
 public static IEnumerator <byte> InstructionAt(this IMemoryBlock memory, ushort address)
 {
     while (true)
     {
         yield return(memory[address++]);
     }
 }
示例#8
0
        public static void Dump(this IMemoryBlock memory, TextWriter output)
        {
            for (int i = 0; i < memory.Size; i++)
            {
                if (i % 16 == 0)
                {
                    output.Write($"0x{i:X4} : ");
                }

                output.Write($"{memory[i]:X2} ");

                if (i % 16 != 15)
                {
                    continue;
                }

                output.Write(": ");
                for (int j = i - 15; j <= i; j++)
                {
                    output.Write(memory[j].ToDisplayableChar());
                    output.Write(" ");
                }

                output.WriteLine();
            }

            output.Flush();
        }
示例#9
0
 /// <summary>
 /// Marks an unallocated contiguous block as allocated
 /// </summary>
 /// <param name="block">newly allocated block</param>
 protected void RemoveFreeBlock(IMemoryBlock block)
 {
     dictStartLoc.Remove(block.StartLocation);
     dictEndLoc.Remove(block.EndLocation);
     if (freeBlocksList[block.Length].Count == 1)
     {
         freeBlocksList.Remove(block.Length);
         if (GetLargest() == block.Length)
         {
             //Get the true largest
             if (freeBlocksList.Count == 0)
             {
                 SetLargest(0);
             }
             else
             {
                 long[] indices = new long[freeBlocksList.Count];
                 freeBlocksList.Keys.CopyTo(indices, 0);
                 SetLargest(indices[indices.LongLength - 1]);
             }
         }
     }
     else
     {
         freeBlocksList[block.Length].Remove(block.StartLocation);
     }
 }
示例#10
0
        private void ReadMask(PipeStream stream)
        {
            IndexOfResult result = stream.IndexOf((int)this.Length);
            int           index  = 0;

            if (result.Start.ID == result.End.ID)
            {
                index = MarkBytes(result.Start.Bytes, result.StartPostion, result.EndPostion, index);
            }
            else
            {
                index = MarkBytes(result.Start.Bytes, result.StartPostion, result.Start.Length - 1, index);
                IMemoryBlock next = result.Start.NextMemory;
                while (next != null)
                {
                    if (next.ID == result.End.ID)
                    {
                        index = MarkBytes(next.Bytes, 0, result.EndPostion, index);
                        break;
                    }
                    else
                    {
                        index = MarkBytes(next.Bytes, 0, next.Length - 1, index);
                    }
                    next = result.Start.NextMemory;
                }
            }
        }
        /// <summary>
        /// Frees an allocated memory block.
        /// </summary>
        /// <param name="allocatedBlock">Allocated memory block to be freed</param>
        /// <remarks>This method does not verify if the allocatedBlock is indeed from this slab. Callers should make sure that the allocatedblock belongs to the right slab.</remarks>
        public void Free(IMemoryBlock allocatedBlock)
        {
            //NOTE: This method can call the pool to do some cleanup (which holds locks), therefore do not call this method from within any lock
            //Or you'll get into a deadlock.

            lock (sync)
            {
                //Attempt to coalesce/merge free blocks around the allocateblock to be freed.
                long?newFreeStartLocation = null;
                long newFreeSize          = 0;

                if (allocatedBlock.StartLocation > 0)
                {
                    //Check if block before this one is free

                    long startLocBefore;
                    if (dictEndLoc.TryGetValue(allocatedBlock.StartLocation - 1, out startLocBefore))
                    {
                        //Yup, so remove the free block
                        newFreeStartLocation = startLocBefore;
                        newFreeSize         += (allocatedBlock.StartLocation - startLocBefore);
                        RemoveFreeBlock(dictStartLoc[startLocBefore], true);
                    }
                }

                //Include  AllocatedBlock
                if (!newFreeStartLocation.HasValue)
                {
                    newFreeStartLocation = allocatedBlock.StartLocation;
                }
                newFreeSize += allocatedBlock.Length;

                if (allocatedBlock.EndLocation + 1 < Size)
                {
                    // Check if block next to (below) this one is free
                    FreeSpace blockAfter;
                    if (dictStartLoc.TryGetValue(allocatedBlock.EndLocation + 1, out blockAfter))
                    {
                        //Yup, remove the free block
                        newFreeSize += blockAfter.Length;
                        RemoveFreeBlock(blockAfter, true);
                    }
                }

                //Mark entire contiguous block as free -- and set Largest if need be:
                //The length of the AddFreeBlock call will always be longer than or equals to any of the RemoveFreeBlock
                // calls, so it's SetLargest logic will always work.
                AddFreeBlock(newFreeStartLocation.Value, newFreeSize, false);
            }

            if (GetLargest() == slabSize)
            {
                //This slab is empty. prod pool to do some cleanup
                if (pool != null)
                {
                    pool.TryFreeSlabs();
                }
            }
        }
示例#12
0
        public void LengthTest()
        {
            IMemoryBlock target = CreateIMemoryBlock();
            long         actual;

            actual = target.Length;
            Assert.AreEqual <long>(length, actual);
        }
示例#13
0
 public MBC1Cartridge(byte[] romData)
 {
     _romData = romData;
     // 32 KByte of RAM (TODO actual available RAM depends on concrete cartridge?)
     _ramData = new byte[32768];
     ROM      = new LambdaMemoryBlock(32768, ReadRom, WriteRom);
     RAM      = new LambdaMemoryBlock(8192, ReadRam, WriteRam);
 }
示例#14
0
        public void StartLocationTest()
        {
            IMemoryBlock target = CreateIMemoryBlock();
            long         actual;

            actual = target.StartLocation;
            Assert.AreEqual <long>(startLoc, actual);
        }
示例#15
0
        public void SlabTest()
        {
            IMemoryBlock target = CreateIMemoryBlock();
            IMemorySlab  actual;

            actual = target.Slab;
            Assert.AreEqual <IMemorySlab>(slab, actual);
        }
示例#16
0
        public static IMemoryBlock CastTo(this IMemoryBlock source, NPTypeCode to)
        {
            switch (to)
            {
#if _REGEN1
	            %foreach supported_dtypes,supported_dtypes_lowercase%
	            case NPTypeCode.#1: return CastTo<#2>(source);
	            %
示例#17
0
 public MBC2Cartridge(byte[] romData)
 {
     _romData = romData;
     // MBC2 has 512 x 4 bits of RAM on addresses 0xA000-0xA1FF.
     _ramData = new byte[512];
     ROM      = new LambdaMemoryBlock(32768, ReadRom, WriteRom);
     RAM      = new LambdaMemoryBlock(8192, ReadRam, WriteRam);
 }
示例#18
0
 public MBC5Cartridge(byte[] romData)
 {
     _romData = romData;
     // Has maximum of 16 banks of 8KBytes each.
     _ramData = new byte[8192 * 16];
     ROM      = new LambdaMemoryBlock(32768, ReadRom, WriteRom);
     RAM      = new LambdaMemoryBlock(8192, ReadRam, WriteRam);
 }
示例#19
0
        /// <summary>
        /// Attempts to allocate a memory block of a specified length.
        /// </summary>
        /// <param name="length">Length, in bytes, of memory block</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>True, if memory block was allocated. False, if otherwise</returns>
        public virtual bool TryAllocate(long length, out IMemoryBlock allocatedBlock)
        {
            allocatedBlock = null;
            lock (sync)
            {
                if (GetLargest() < length)
                {
                    return(false);
                }

                //search freeBlocksList looking for the smallest available free block
                long[] keys = new long[freeBlocksList.Count];
                freeBlocksList.Keys.CopyTo(keys, 0);
                int index = System.Array.BinarySearch <long>(keys, length);
                if (index < 0)
                {
                    index = ~index;
                    if (index >= keys.LongLength)
                    {
                        return(false);
                    }
                }

                //Grab the first memoryblock in the freeBlockList innerSortedDictionary
                //There is guanranteed to be an innerSortedDictionary with at least 1 key=value pair
                IMemoryBlock foundBlock = null;
                foreach (KeyValuePair <long, IMemoryBlock> kvPair in freeBlocksList[keys[index]])
                {
                    foundBlock = kvPair.Value;
                    break;
                }

                //Remove existing free block
                RemoveFreeBlock(foundBlock);


                if (foundBlock.Length == length)
                {
                    //Perfect match
                    allocatedBlock = foundBlock;
                }
                else
                {
                    //FoundBlock is larger than requested block size

                    allocatedBlock = new MemoryBlock(foundBlock.StartLocation, length, this);

                    long newFreeStartLocation = allocatedBlock.EndLocation + 1;
                    long newFreeSize          = foundBlock.Length - length;

                    //add new Freeblock with the smaller remaining space
                    AddFreeBlock(newFreeStartLocation, newFreeSize);
                }
            }

            return(true);
        }
示例#20
0
 /// <summary>
 /// Initializes a new instance of the ManagedBuffer class, specifying the memory block that the ManagedBuffer reads and writes to.
 /// </summary>
 /// <param name="allocatedMemoryBlock">Underlying allocated memory block</param>
 internal ManagedBuffer(IMemoryBlock allocatedMemoryBlock)
 {
     if (allocatedMemoryBlock == null)
     {
         throw new ArgumentNullException("AllocatedMemoryBlock");
     }
     memoryBlock = allocatedMemoryBlock;
     slabArray   = null;
 }
示例#21
0
        public void EndLocationTest()
        {
            //Correct Property
            IMemoryBlock target = CreateIMemoryBlock();
            long         actual;

            actual = target.EndLocation;
            Assert.AreEqual <long>(startLoc + length - 1, actual);
        }
示例#22
0
 /// <summary>
 /// Initializes a new instance of the ManagedBuffer class, specifying the slab to be associated with the ManagedBuffer.
 /// This constructor creates an empty (zero-length) buffer.
 /// </summary>
 /// <param name="slab">The Memory Slab to be associated with the ManagedBuffer</param>
 internal ManagedBuffer(IMemorySlab slab)
 {
     if (slab == null)
     {
         throw new ArgumentNullException("SlabArray");
     }
     memoryBlock    = null;
     this.slabArray = slab.Array;
 }
示例#23
0
        public void TryAllocateTest3()
        {
            IMemorySlab target = CreateIMemorySlab();

            //allocate invalid length
            long         badLength      = -1;
            IMemoryBlock allocatedBlock = null;
            bool         result1        = target.TryAllocate(badLength, out allocatedBlock);
        }
示例#24
0
        public ReadOnlyMemoryWindow([NotNull] IMemoryBlock memoryBlock)
        {
            if (memoryBlock == null)
            {
                throw new ArgumentNullException(nameof(memoryBlock));
            }

            Pointer = memoryBlock.GetPointer();
            Size    = memoryBlock.Size;
        }
示例#25
0
        /// <summary>
        ///     Copies the entire contents of this storage to given address (using <see cref="Count"/>).
        /// </summary>
        /// <param name="dst">The block to copy to.</param>
        public static unsafe void CopyTo(this IMemoryBlock src, void *dstAddress, int countOffsetDesitinion)
        {
            if (dstAddress == null)
            {
                throw new ArgumentNullException(nameof(dstAddress));
            }

            var bytesCount = src.BytesLength;

            Buffer.MemoryCopy(src.Address, (byte *)dstAddress + countOffsetDesitinion * src.ItemLength, bytesCount, bytesCount);
        }
示例#26
0
        /// <summary>
        /// Frees an allocated memory block.
        /// </summary>
        /// <param name="allocatedBlock">Allocated memory block to be freed</param>
        /// <remarks>This method does not detect if the allocatedBlock is indeed from this slab. Callers should make sure that the allocatedblock belongs to the right slab.</remarks>
        public virtual void Free(IMemoryBlock allocatedBlock)
        {
            lock (sync)
            {
                //Attempt to coalesce/merge free blocks around the allocateblock to be freed.
                long?newFreeStartLocation = null;
                long newFreeSize          = 0;

                if (allocatedBlock.StartLocation > 0)
                {
                    //Check if block before this one is free

                    IMemoryBlock blockBefore;
                    if (dictEndLoc.TryGetValue(allocatedBlock.StartLocation - 1, out blockBefore))
                    {
                        //Yup, so delete it
                        newFreeStartLocation = blockBefore.StartLocation;
                        newFreeSize         += blockBefore.Length;
                        RemoveFreeBlock(blockBefore);
                    }
                }

                //Include  AllocatedBlock
                if (!newFreeStartLocation.HasValue)
                {
                    newFreeStartLocation = allocatedBlock.StartLocation;
                }
                newFreeSize += allocatedBlock.Length;

                if (allocatedBlock.EndLocation + 1 < Size)
                {
                    // Check if block next to (below) this one is free
                    IMemoryBlock blockAfter;
                    if (dictStartLoc.TryGetValue(allocatedBlock.EndLocation + 1, out blockAfter))
                    {
                        //Yup, delete it
                        newFreeSize += blockAfter.Length;
                        RemoveFreeBlock(blockAfter);
                    }
                }

                //Mark entire contiguous block as free
                AddFreeBlock(newFreeStartLocation.Value, newFreeSize);
            }

            if (GetLargest() == Size)
            {
                //This slab is empty. prod pool to do some cleanup
                if (pool != null)
                {
                    pool.TryFreeSlab();
                }
            }
        }
示例#27
0
        /// <summary>
        ///     Copies the entire contents of this storage to given address.
        /// </summary>
        /// <param name="src">The source of the copying</param>
        /// <param name="dstAddress">The address to copy to.</param>
        public static unsafe void CopyTo(this IMemoryBlock src, void *dstAddress)
        {
            if (dstAddress == null)
            {
                throw new ArgumentNullException(nameof(dstAddress));
            }

            var bytesCount = src.BytesLength;

            Buffer.MemoryCopy(src.Address, dstAddress, bytesCount, bytesCount);
        }
示例#28
0
        public UnmanagedStream([NotNull] IReadWriteMemory memory)
        {
            if (memory == null)
            {
                throw new ArgumentNullException(nameof(memory));
            }

            mMemory  = memory;
            CanRead  = true;
            CanSeek  = true;
            CanWrite = true;
        }
示例#29
0
        public MemoryWindow([NotNull] IMemoryBlock memoryBlock)
        {
            if (memoryBlock == null)
            {
                throw new ArgumentNullException(nameof(memoryBlock));
            }

            Pointer = memoryBlock.GetPointer();
            Size    = memoryBlock.Size;

            mReadable = memoryBlock is IReadableMemory;
            mWritable = memoryBlock is IWritableMemory;
        }
示例#30
0
        public static Bitmap RenderTilemapSmall(IMemoryBlock vram, IRegister <bool> tilemapSelect)
        {
            var tilemap       = new Bitmap(32, 32);
            var tilemapOffset = tilemapSelect.Value ? 0x1C00 : 0x1800;

            for (int i = 0; i < 1024; i++)
            {
                var x         = i % 32;
                var y         = i / 32;
                var tileIndex = vram[tilemapOffset + y * 32 + x];
                tilemap[x, y] = tileIndex != 0 ? new Pixel(tileIndex, tileIndex, tileIndex) : new Pixel(0xFF, 0xFF, 0xFF);
            }

            return(tilemap);
        }
示例#31
0
        /// <summary>
        /// Attempts to allocate a memory block of a specified length.
        /// </summary>
        /// <param name="length">Length, in bytes, of memory block</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>True, if memory block was allocated. False, if otherwise</returns>
        public virtual bool TryAllocate(long length, out IMemoryBlock allocatedBlock)
        {
            allocatedBlock = null;
            lock (sync)
            {
                if (GetLargest() < length) return false;

                //search freeBlocksList looking for the smallest available free block
                long[] keys = new long[freeBlocksList.Count];
                freeBlocksList.Keys.CopyTo(keys, 0);
                int index = System.Array.BinarySearch<long>(keys, length);
                if (index < 0)
                {
                    index = ~index;
                    if (index >= keys.LongLength)
                    {
                        return false;
                    }
                }

                //Grab the first memoryblock in the freeBlockList innerSortedDictionary
                //There is guanranteed to be an innerSortedDictionary with at least 1 key=value pair
                IMemoryBlock foundBlock = null;
                foreach (KeyValuePair<long, IMemoryBlock> kvPair in freeBlocksList[keys[index]])
                {
                    foundBlock = kvPair.Value;
                    break;
                }

                //Remove existing free block
                RemoveFreeBlock(foundBlock);

                if (foundBlock.Length == length)
                {
                    //Perfect match
                    allocatedBlock = foundBlock;
                }
                else
                {
                    //FoundBlock is larger than requested block size

                    allocatedBlock = new MemoryBlock(foundBlock.StartLocation, length, this);

                    long newFreeStartLocation = allocatedBlock.EndLocation + 1;
                    long newFreeSize = foundBlock.Length - length;

                    //add new Freeblock with the smaller remaining space
                    AddFreeBlock(newFreeStartLocation, newFreeSize);

                }

            }

            return true;
        }
示例#32
0
        /// <summary>
        /// Frees an allocated memory block.
        /// </summary>
        /// <param name="allocatedBlock">Allocated memory block to be freed</param>
        /// <remarks>This method does not verify if the allocatedBlock is indeed from this slab. Callers should make sure that the allocatedblock belongs to the right slab.</remarks>
        public void Free(IMemoryBlock allocatedBlock)
        {
            //NOTE: This method can call the pool to do some cleanup (which holds locks), therefore do not call this method from within any lock
            //Or you'll get into a deadlock.

            lock (sync)
            {
                //Attempt to coalesce/merge free blocks around the allocateblock to be freed.
                long? newFreeStartLocation = null;
                long newFreeSize = 0;

                if (allocatedBlock.StartLocation > 0)
                {

                    //Check if block before this one is free

                    long startLocBefore;
                    if (dictEndLoc.TryGetValue(allocatedBlock.StartLocation - 1, out startLocBefore))
                    {
                        //Yup, so remove the free block
                        newFreeStartLocation = startLocBefore;
                        newFreeSize += (allocatedBlock.StartLocation - startLocBefore);
                        RemoveFreeBlock(dictStartLoc[startLocBefore], true);
                    }

                }

                //Include  AllocatedBlock
                if (!newFreeStartLocation.HasValue) newFreeStartLocation = allocatedBlock.StartLocation;
                newFreeSize += allocatedBlock.Length;

                if (allocatedBlock.EndLocation + 1 < Size)
                {
                    // Check if block next to (below) this one is free
                    FreeSpace blockAfter;
                    if (dictStartLoc.TryGetValue(allocatedBlock.EndLocation + 1, out blockAfter))
                    {
                        //Yup, remove the free block
                        newFreeSize += blockAfter.Length;
                        RemoveFreeBlock(blockAfter, true);
                    }
                }

                //Mark entire contiguous block as free -- and set Largest if need be:
                //The length of the AddFreeBlock call will always be longer than or equals to any of the RemoveFreeBlock
                // calls, so it's SetLargest logic will always work.
                AddFreeBlock(newFreeStartLocation.Value, newFreeSize, false);

            }

            if (GetLargest() == slabSize)
            {
                //This slab is empty. prod pool to do some cleanup
                if (pool != null)
                {
                    pool.TryFreeSlabs();
                }
            }
        }
示例#33
0
 /// <summary>
 /// Attempts to allocate a memory block of a specified length.
 /// </summary>
 /// <param name="length">Length, in bytes, of memory block</param>
 /// <param name="allocatedBlock">Allocated memory block</param>
 /// <returns>True, if memory block was allocated. False, if otherwise</returns>
 public bool TryAllocate(long length, out IMemoryBlock allocatedBlock)
 {
     return TryAllocate(length, length, out allocatedBlock) > 0;
 }
 //****************************************************
 // Method: Partition
 //
 // Purpose: Constructor initializes the partition.
 //****************************************************
 public Partition(int partitionNumber, int absoluteStartingAddress, IMemoryBlock memoryBlock)
 {
     this.partitionNumber = partitionNumber;
     this.absoluteStartingAddress = absoluteStartingAddress;
     this.memoryBlock = memoryBlock;
 }
示例#35
0
 /// <summary>
 /// Initializes a new instance of the ManagedBuffer class, specifying the memory block that the ManagedBuffer reads and writes to.
 /// </summary>
 /// <param name="allocatedMemoryBlock">Underlying allocated memory block</param>
 internal ManagedBuffer(IMemoryBlock allocatedMemoryBlock)
 {
     if (allocatedMemoryBlock == null) throw new ArgumentNullException("AllocatedMemoryBlock");
     memoryBlock = allocatedMemoryBlock;
     slabArray = null;
 }
示例#36
0
        /// <summary>
        /// Helper method that searches for free block in an array of slabs and returns the allocated block
        /// </summary>
        /// <param name="length">Requested length of memory block</param>
        /// <param name="slabs">Array of slabs to search</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>True if memory block was successfully allocated. False, if otherwise</returns>
        private static bool TryAllocateBlockInSlabs(long length, IMemorySlab[] slabs, out IMemoryBlock allocatedBlock)
        {
            allocatedBlock = null;
            for (int i = 0; i < slabs.Length; i++)
            {
                if (slabs[i].LargestFreeBlockSize >= length)
                {
                    if (slabs[i].TryAllocate(length, out allocatedBlock))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
示例#37
0
 /// <summary>
 /// Initializes a new instance of the ManagedBuffer class, specifying the slab to be associated with the ManagedBuffer.
 /// This constructor creates an empty (zero-length) buffer.
 /// </summary>
 /// <param name="slab">The Memory Slab to be associated with the ManagedBuffer</param>
 internal ManagedBuffer(IMemorySlab slab)
 {
     if (slab == null) throw new ArgumentNullException("SlabArray");
     memoryBlock = null;
     this.slabArray = slab.Array;
 }
示例#38
0
 public void BufferConstructorTest2()
 {
     IMemoryBlock[] emptyBlocks = new IMemoryBlock[0];
     ManagedBuffer target = new ManagedBuffer(emptyBlocks);
 }
示例#39
0
 /// <summary>
 /// Marks an unallocated contiguous block as allocated
 /// </summary>
 /// <param name="block">newly allocated block</param>
 protected void RemoveFreeBlock(IMemoryBlock block)
 {
     dictStartLoc.Remove(block.StartLocation);
     dictEndLoc.Remove(block.EndLocation);
     if (freeBlocksList[block.Length].Count == 1)
     {
         freeBlocksList.Remove(block.Length);
         if (GetLargest() == block.Length)
         {
             //Get the true largest
             if (freeBlocksList.Count == 0)
             {
                 SetLargest(0);
             }
             else
             {
                 long[] indices = new long[freeBlocksList.Count];
                 freeBlocksList.Keys.CopyTo(indices, 0);
                 SetLargest(indices[indices.LongLength - 1]);
             }
         }
     }
     else
     {
         freeBlocksList[block.Length].Remove(block.StartLocation);
     }
 }
示例#40
0
        /// <summary>
        /// Attempts to allocate a memory block of length between minLength and maxLength (both inclusive)
        /// </summary>
        /// <param name="minLength">The minimum acceptable length</param>
        /// <param name="maxLength">The maximum acceptable length</param>
        /// <param name="allocatedBlock">Allocated memory block</param>
        /// <returns>Length of allocated block if successful, zero otherwise</returns>
        /// <remarks>This overload is useful when multiple threads are concurrently working on the slab and the caller wants to allocate a block up to a desired size</remarks>
        public long TryAllocate(long minLength, long maxLength, out IMemoryBlock allocatedBlock)
        {
            if (minLength > maxLength) throw new ArgumentException("minLength is greater than maxLength", "minLength");
            if (minLength <= 0) throw new ArgumentOutOfRangeException("minLength must be greater than zero", "minLength");
            if (maxLength <= 0) throw new ArgumentOutOfRangeException("maxLength must be greater than zero", "maxLength");

            allocatedBlock = null;
            lock (sync)
            {
                if (freeBlocksList.Count == 0) return 0;

                long[] keys = new long[freeBlocksList.Count];
                freeBlocksList.Keys.CopyTo(keys, 0);

                //Leave if the largest free block cannot hold minLength
                if (keys[keys.LongLength - 1] < minLength)
                {
                    return 0;
                }

                //search freeBlocksList looking for the smallest available free block than can fit maxLength
                long length = maxLength;
                int index = System.Array.BinarySearch<long>(keys, maxLength);
                if (index < 0)
                {
                    index = ~index;
                    if (index >= keys.Length)
                    {
                        //index is set to the largest free block which can hold minLength
                        index = keys.Length - 1;

                        //length is set to the size of that free block
                        length = keys[index];
                    }
                }

                //Grab the first memoryblock in the freeBlockList innerSortedDictionary
                //There is guanranteed to be at least one in the innerList
                FreeSpace foundBlock = dictStartLoc[freeBlocksList[keys[index]][0]];

                if (foundBlock.Length == length)
                {
                    //Perfect match:

                    //Remove existing free block -- and set Largest if need be
                    RemoveFreeBlock(foundBlock, false);

                    allocatedBlock = new MemoryBlock(foundBlock.Offset, foundBlock.Length, this);
                }
                else
                {
                    //FoundBlock is larger than requested block size

                    //Shrink the existing free memory block by the new allocation
                    ShrinkFreeMemoryBlock(foundBlock, foundBlock.Length - length);

                    allocatedBlock = new MemoryBlock(foundBlock.Offset, length, this);
                }

                return length;
            }
        }
示例#41
0
        /// <summary>
        /// Frees an allocated memory block.
        /// </summary>
        /// <param name="allocatedBlock">Allocated memory block to be freed</param>
        /// <remarks>This method does not detect if the allocatedBlock is indeed from this slab. Callers should make sure that the allocatedblock belongs to the right slab.</remarks>
        public virtual void Free(IMemoryBlock allocatedBlock)
        {
            lock (sync)
            {

                //Attempt to coalesce/merge free blocks around the allocateblock to be freed.
                long? newFreeStartLocation = null;
                long newFreeSize = 0;

                if (allocatedBlock.StartLocation > 0)
                {

                    //Check if block before this one is free

                    IMemoryBlock blockBefore;
                    if (dictEndLoc.TryGetValue(allocatedBlock.StartLocation - 1, out blockBefore))
                    {
                        //Yup, so delete it
                        newFreeStartLocation = blockBefore.StartLocation;
                        newFreeSize += blockBefore.Length;
                        RemoveFreeBlock(blockBefore);
                    }

                }

                //Include  AllocatedBlock
                if (!newFreeStartLocation.HasValue) newFreeStartLocation = allocatedBlock.StartLocation;
                newFreeSize += allocatedBlock.Length;

                if (allocatedBlock.EndLocation + 1 < Size)
                {
                    // Check if block next to (below) this one is free
                    IMemoryBlock blockAfter;
                    if (dictStartLoc.TryGetValue(allocatedBlock.EndLocation + 1, out blockAfter))
                    {
                        //Yup, delete it
                        newFreeSize += blockAfter.Length;
                        RemoveFreeBlock(blockAfter);
                    }
                }

                //Mark entire contiguous block as free
                AddFreeBlock(newFreeStartLocation.Value, newFreeSize);

            }

            if (GetLargest() == Size)
            {
                //This slab is empty. prod pool to do some cleanup
                if (pool != null)
                {
                    pool.TryFreeSlab();
                }
            }
        }