前面对内存池已经有了一个大致的复习,现在实现一个简单的固定内存池
一、MemoryPool.h
#ifndef __SOFT_COLLECTION_H__
#define __SOFT_COLLECTION_H__
#include <iostream>
#include <string>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <memory.h>
#define MEMPOOL_ALIGNMENT 8
struct memory_block
{
//参数直接赋值
memory_block(unsigned short type = 1, unsigned short unit_size = 0);
virtual ~memory_block(){};
unsigned short size;
unsigned short free;
unsigned short first;
//unsigned short dummy_align;
memory_block* next;
char data[1];
static void* operator new(size_t, unsigned short type, unsigned short unit_size)
{
return ::operator new(sizeof(memory_block) + type * unit_size);
}
static void operator delete(void* p, size_t)
{
::operator delete(p);
}
};
class memory_pool
{
public:
//第一个参数动态分配(构建对象时分配),后两个参数直接赋值
memory_pool(unsigned short _unit_size, unsigned short _init_size = 1024, unsigned short _grow_size = 256);
virtual ~memory_pool();
void* alloc();
void free(void* _free);
//void safety_alloc();
void safety_free(void* _pfree);
memory_block* new_init_block() const
{
return new(init_size, unit_size) memory_block(init_size, unit_size);
}
memory_block* new_grow_block() const
{
return new(grow_size, unit_size) memory_block(grow_size, unit_size);
}
private:
memory_block* block;
unsigned short unit_size;
unsigned short init_size;
unsigned short grow_size;
};
#endif
二、MemoryPool.cpp
#include "MemoryPool.h"
#include <pthread.h>
#include <unistd.h>
memory_block::memory_block(unsigned short type, unsigned short unit_size)
:size(type * unit_size),
free(type - 1),
first(1),
next(0)
{
char* _data = data;
for(unsigned short i = 1; i < type; ++i)
{
*reinterpret_cast<unsigned short*>(_data) = i;
_data += unit_size;
}
}
memory_pool::memory_pool(unsigned short _unit_size, unsigned short _init_size, unsigned short _grow_size)
:block(nullptr),
unit_size(_unit_size),
init_size(_init_size),
grow_size(_grow_size)
{
if(_unit_size <= 2)
{
unit_size = 2;
}
else if(_unit_size > 4)
{
unit_size = (_unit_size + (MEMPOOL_ALIGNMENT - 1)) & ~(MEMPOOL_ALIGNMENT - 1);
}
else
{
unit_size = 4;
}
}
memory_pool::~memory_pool()
{
memory_block* _block = block;
while(_block)
{
memory_block* temp = _block->next;
delete _block;
_block = temp;
}
}
void* memory_pool::alloc()
{
if(!block)
{
block = new_init_block();
if(!block)
return nullptr;
return (void*)(block->data);
}
memory_block* _block = block;
while(_block && !_block->free)
{
_block = _block->next;
}
if(_block)
{
char* _free = _block->data + (_block->first * unit_size);
_block->first = *((unsigned short*)_free);
_block->free--;
return (void*)_free;
}
else
{
if(grow_size)
return nullptr;
_block = new_grow_block();
if(!block)
return nullptr;
_block->next = block->next;
block->next = _block;
return (void*)(_block->data);
}
}
void memory_pool::free(void* _free)
{
memory_block* _block = block;
memory_block* prev = nullptr;
while(((unsigned long)_block->data > (unsigned long)_free) ||
((unsigned long)_free >= ((unsigned long)_block->data + _block->size)))
{
prev = _block;
_block = _block->next;
if(!_block)
return;
}
_block->free++;
*((unsigned short*)_free) = _block->first;
_block->first = (unsigned short)(((unsigned long)_free - (unsigned long)(_block->data)) / unit_size);
if(prev && (_block->free * unit_size == _block->size))
{
prev->next = _block->next;
delete _block;
}
else
{
if(prev)
{
prev->next = _block->next;
_block->next = block->next;
block->next = _block;
}
}
}