Created
July 30, 2013 02:06
-
-
Save timonwong/6109617 to your computer and use it in GitHub Desktop.
弱爆的内存池实现
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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