public static IntPtr Alloc( int size )
{
lock ( memoryBlocks )
{
// allocate memory block without caching if cache is not available
if ( ( busyBlocks >= maximumCacheSize ) || ( size > maxSizeToCache ) || ( size < minSizeToCache ) )
return Marshal.AllocHGlobal( size );
// if all cached blocks are busy, create new cache block
if ( currentCacheSize == busyBlocks )
{
IntPtr memoryBlock = Marshal.AllocHGlobal( size );
memoryBlocks.Add( new CacheBlock( memoryBlock, size ) );
busyBlocks++;
currentCacheSize++;
cachedMemory += size;
return memoryBlock;
}
// find free memory block with enough memory
for ( int i = 0; i < currentCacheSize; i++ )
{
CacheBlock block = memoryBlocks[i];
if ( ( block.Free == true ) && ( block.Size >= size ) )
{
block.Free = false;
busyBlocks++;
return block.MemoryBlock;
}
}
// finaly find first free memory block and resize it
for ( int i = 0; i < currentCacheSize; i++ )
{
CacheBlock block = memoryBlocks[i];
if ( block.Free == true )
{
// remove this block cache
Marshal.FreeHGlobal( block.MemoryBlock );
memoryBlocks.RemoveAt( i );
currentCacheSize--;
cachedMemory -= block.Size;
// add new one
IntPtr memoryBlock = Marshal.AllocHGlobal( size );
memoryBlocks.Add( new CacheBlock( memoryBlock, size ) );
busyBlocks++;
currentCacheSize++;
cachedMemory += size;
return memoryBlock;
}
}
return IntPtr.Zero;
}
}