public byte *Malloc(int size, bool counterBased) { int idx = _blockPool.Pop(); var ptr = &_data[idx * _physicalBlockSize]; var header = (BlockHeader *)ptr; header->BlockIndex = idx; header->PtrSize = size; header->BlocksSize = _blocksSize; header->SegmentIndex = _segmentIndex; header->ReferenceCount = counterBased ? 1 : 0; Interlocked.Decrement(ref _freeBlocks); return(ptr + BlockHeader.SIZE); }
// ****************************************************************************************** // // ********** STATISTICS public static byte *New(int size, bool counterBased = false, bool overSized = false) { byte *ptr = null; int q = SizeToQueue(size + (overSized ? size * 2 : 0)); int mem = -1; // -------- Reduced contention with minimal instructions count lock (_locker) { int idx = _pool.FirstOfQueue(q); if (idx == -1) { idx = _pool.Pop(); _pool.Enqueue(idx, q); int segsSize = 0; int blocksSize = 0; SizeToSegmentProperties(size + (overSized ? size * 2 : 0), out segsSize, out blocksSize); _segments[idx].Build(segsSize, blocksSize, idx, out mem); ptr = _segments[idx].Malloc(size, counterBased); } else { ptr = _segments[idx].Malloc(size, counterBased); if (_segments[idx].FreeBlocks == 0) { _pool.Enqueue(idx, q + 1); } } } // -------- Update statistics Interlocked.Add(ref _totalMemory, size); Interlocked.Increment(ref _totalBlockCount); if (mem != -1) { Interlocked.Add(ref _totalBufferSpace, mem); Interlocked.Increment(ref _totalSegmentCount); } return(ptr); }