ppsspp/Core/Util/BlockAllocator.h
Unknown W. Brackets ecd5062617 Leave free space for alignment "holes" in mem.
This allows other, small allocates to fit in these spaces, which happens
in some games (like Gods Eater Burst.)
2015-10-09 20:08:02 +08:00

90 lines
2.3 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
class PointerWrap;
#include "Common/CommonTypes.h"
// Generic allocator thingy. Allocates blocks from a range.
class BlockAllocator
{
public:
BlockAllocator(int grain = 16); // 16 byte granularity by default.
~BlockAllocator();
void Init(u32 _rangeStart, u32 _rangeSize);
void Shutdown();
void ListBlocks() const;
// WARNING: size can be modified upwards!
u32 Alloc(u32 &size, bool fromTop = false, const char *tag = 0);
u32 AllocAligned(u32 &size, u32 sizeGrain, u32 grain, bool fromTop = false, const char *tag = 0);
u32 AllocAt(u32 position, u32 size, const char *tag = 0);
bool Free(u32 position);
bool FreeExact(u32 position);
bool IsBlockFree(u32 position) {
Block *b = GetBlockFromAddress(position);
if (b)
return !b->taken;
else
return false;
}
u32 GetBlockStartFromAddress(u32 addr) const;
u32 GetBlockSizeFromAddress(u32 addr) const;
u32 GetLargestFreeBlockSize() const;
u32 GetTotalFreeBytes() const;
const char *GetBlockTag(u32 addr) const;
void DoState(PointerWrap &p);
private:
void CheckBlocks() const;
struct Block
{
Block(u32 _start, u32 _size, bool _taken, Block *_prev, Block *_next);
void SetTag(const char *_tag);
void DoState(PointerWrap &p);
u32 start;
u32 size;
bool taken;
char tag[32];
Block *prev;
Block *next;
};
Block *bottom_;
Block *top_;
u32 rangeStart_;
u32 rangeSize_;
u32 grain_;
void MergeFreeBlocks(Block *fromBlock);
Block *GetBlockFromAddress(u32 addr);
const Block *GetBlockFromAddress(u32 addr) const;
Block *InsertFreeBefore(Block *b, u32 size);
Block *InsertFreeAfter(Block *b, u32 size);
};