Skip to content

Instantly share code, notes, and snippets.

@timonwong
Created July 30, 2013 02:06
Show Gist options
  • Save timonwong/6109617 to your computer and use it in GitHub Desktop.
Save timonwong/6109617 to your computer and use it in GitHub Desktop.
弱爆的内存池实现
// g++ -std=c++11
#include <cstdio>
#include <new>
#include <vector>
using std::size_t;
using std::vector;
using std::bad_alloc;
// 固定大小内存池, 非常基本的演示
template<size_t _BLOCK_SIZE = 64, size_t _NUM_BLOCKS = 16>
class fixed_mem_pool
{
union obj
{
union obj *next;
char client_data[1];
};
public:
enum
{
BLOCK_SIZE = _BLOCK_SIZE,
NUM_BLOCKS = _NUM_BLOCKS
};
public:
fixed_mem_pool()
{
// 连续分配一块内存, 初始化时分成`NUM_BLOCKS`份
chunks_ = new char[BLOCK_SIZE * NUM_BLOCKS];
free_list_head_ = reinterpret_cast<obj *>(chunks_);
auto cur_obj = free_list_head_;
auto next_block_ptr = free_list_head_->client_data + BLOCK_SIZE;
// 构建free_list(链表), 标记可用内存
for (auto i = 1; i < NUM_BLOCKS; i++)
{
cur_obj->next = reinterpret_cast<obj *>(next_block_ptr);
cur_obj = cur_obj->next;
next_block_ptr += BLOCK_SIZE;
}
cur_obj->next = nullptr;
}
~fixed_mem_pool()
{
delete chunks_;
}
void *allocate()
{
if (free_list_head_ == nullptr)
{
throw bad_alloc();
}
// Take block from head directy.
void *p = free_list_head_;
free_list_head_ = free_list_head_->next;
// Remember, The size of this block is `BLOCK_SIZE`.
return p;
}
void free(void *p)
{
// Return ptr back to free list
auto head = reinterpret_cast<obj *>(p);
head->next = free_list_head_;
free_list_head_ = head;
}
// print free list strucutre
void diagnose()
{
printf("----------------------------------\n");
printf("Blocks: %4d, block size: %4d\n", blocks(), block_size());
auto p = free_list_head_;
while (p != nullptr)
{
printf("free block @ %p\n", p);
p = p->next;
}
printf("----------------------------------\n");
}
inline size_t blocks() const
{
return NUM_BLOCKS;
}
inline size_t block_size() const
{
return BLOCK_SIZE;
}
private:
char *chunks_;
obj *free_list_head_;
};
int main()
{
// Create a memory pool, with 4 blocks, each block size is 64.
fixed_mem_pool<64, 4> mempool;
mempool.diagnose();
vector<char *> blocks;
for (auto i = 0; i < mempool.blocks(); i++)
{
char *p = reinterpret_cast<char *>(mempool.allocate());
blocks.push_back(p);
printf("Got a free block, addr @ %p\n", p);
}
try
{
// Will bad_alloc because no free block in mempool
mempool.allocate();
}
catch (bad_alloc &)
{
printf("Allocated %u memory blocks, each of size %u\n", blocks.size(), mempool.block_size());
}
// Use the blocks, this is just a naive demonstration...
for (auto i = 0; i < blocks.size(); i++)
{
snprintf(blocks[i], mempool.block_size(), "This is allocated block #%d.\n", i + 1);
}
// Return all blocks back
for (auto block : blocks)
{
mempool.free(block);
}
blocks.clear();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment