伪代码,作记录用:
写的都只是思路上的代码,未运行过;
// @author Jave.Lin
// @date 2016-04-16 16:41
function getPOT(n:Number):Number
{
var v:Number = 1;
while (n < v) v <<= 1;
return v;
}
// mem block
public class Block
{
public var off_s:int;
public var len:int;
public var free:bool;
public var nextBlock:Block;
public function split(size:int):Bloack
{
if (free == false) return null;
var pot_s:int = getPOT(size);
if (len <= pot_s) return null;
var r:Block = new Block();
r.off_s = off_s;
r.len = pot_s;
r.free = true;
r.nextBlock = this;
off_s += pot_s;
len -= pot_s;
return r;
}
public function mergeNextBlock():Boolean
{
return merge(nextBlock);
}
public function merge(block:Bloack):Boolean
{
if (block == null || free == false) return false;
len += block.len;
nextBlock = block.nextBloack;
block.nextBloack = null;
return true;
}
}
// mem block heap
public class Heap
{
private var _byte:*Number = NULL;
private var _size:int = 0;
private var _blocks:Block[];
public function Heap(pot_size:int)
{
allocBs(pot_size);
}
private var _lastCanUseContinueIdx:int = -1;
private var _lastCanUseContinueSize:int = -1;
public function freeBlock(b:Block):void
{
b.free = true;
}
// must be pot size
public function getBlock(pot_s:int, os:int = 0):Block
{
for (var i:int = os; i < _size; ++i)
{
var b:Bloack = _blocks[i];
if (b.free)
{
if (b.size >= pot_s)
{
var sb:Block = b.split(pot_s);
if (sb != null)
{
_blocks[i] = sb;
var lb:Block = sb.nextBlock;
do
{ _blocks[++i] = lb.nextBlock;
} while (lb.nextBlock);
return sb;
}
else
{
return b;
}
}
else
{
if (_lastCanUseContinueIdx == -1)
{
_lastCanUseContinueIdx = i;
_lastCanUseContinueSize = b.len;
}
else
{
_lastCanUseContinueSize += b.len;
}
if (_lastCanUseContinueSize >= pot_s)
{
var lastB:Bloack = _blocks[_lastCanUseContinueIdx];
var subLen:int = i - _lastCanUseContinueIdx;
var mergeCount:int = subLen;
while (mergeCount > 0)
{
lastB.mergeNextBlock();
mergeCount--;
}
_blocks.split(i + 1, subLen);
return lastB;
}
}
}
else
{
_lastCanUseContinueIdx = -1;
_lastCanUseContinueSize = -1;
}
}
raiseCap();
return getBlock(size, _lastCanUseContinueIdx);
}
private function allocBs(pot_size:int):void
{
if (_size < pot_size)
{
var ps:int = _size;
_size = pot_size;
var b:Bloack = new Bloack();
if (_byte == NULL)
{
_byte = alloc(_size * sizeof(Number));
b.off_s = 0;
b.len = _size;
b.free = true;
b.nextBlock = null;
_blocks.push(b);
}
else
{
_byte = realloc(_byte, _size * sizeof(Number));
b = new Block();
b.off_s = ps;
b.len = _size - ps;
b.free = true;
b.nextBloack = null;
_blocks[_blocks.length - 1].nextBlock = b;
}
}
}
private function raiseCap():void
{
allocBs(getPOT(_size + 1);
}
}