1.内存池后端
#ifndef ALLOCATOR_H
#define ALLOCATOR_H
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include "Mutex.h"
class Allocator
{
public:
enum {ALIGN = 8};
enum {MAX_BYTES = 128};
enum {NFREELISTS = MAX_BYTES / ALIGN};
union Obj {
union Obj* next;
char data[1];
};
static void* allocate(uint32_t size);
static void deallocate(void* p, uint32_t size);
private:
Allocator() : mStartFree(NULL), mEndFree(NULL), mHeapSize(0)
{
mMutex = new Mutex;
memset(mFreeList, 0, sizeof(mFreeList));
};
~Allocator() {
};
static Allocator* getInstance();
void* alloc(uint32_t size);
void dealloc(void* p, uint32_t size);
uint32_t freelistIndex(uint32_t bytes) {
return (((bytes) + ALIGN-1) / ALIGN - 1);
}
uint32_t roundup(uint32_t bytes) {
return (((bytes) + ALIGN-1) & ~(ALIGN - 1));
}
void *refill(uint32_t bytes);
char* chunkAlloc(uint32_t size, int& nobjs);
private:
static Allocator* mAllocator;
Mutex* mMutex;
char* mStartFree;
char* mEndFree;
uint32_t mHeapSize;
Obj* mFreeList[NFREELISTS];
};
#endif
#include "Allocator.h"
#include <cstdlib>
#include <iostream>
Allocator* Allocator::mAllocator = NULL;
void* Allocator::allocate(uint32_t size)
{
return getInstance()->alloc(size);
}
void Allocator::deallocate(void* p, uint32_t size)
{
getInstance()->dealloc(p, size);
}
Allocator* Allocator::getInstance()
{
if(!mAllocator)
mAllocator = new Allocator();
return mAllocator;
}
void* Allocator::alloc(uint32_t size)
{
Obj* result;
uint32_t index;
MutexLockGuard mutexLockGuard(mMutex);
if(size > MAX_BYTES)
return malloc(size);
index = freelistIndex(size);
result = mFreeList[index];
if(!result)
{
void* r = refill(roundup(size));
return r;
}
mFreeList[index] = result->next;
return result;
}
void Allocator::dealloc(void* p, uint32_t size)
{
Obj* obj = (Obj*)p;
uint32_t index;
MutexLockGuard mutexLockGuard(mMutex);
if(size > MAX_BYTES)
free(p);
index = freelistIndex(size);
obj->next = mFreeList[index];
mFreeList[index] = obj;
}
void* Allocator::refill(uint32_t bytes)
{
int nobjs = 20;
char* chunk = chunkAlloc(bytes, nobjs);
Obj* result;
Obj* currentObj;
Obj* nextObj;
int i;
uint32_t index;
if(1 == nobjs)
return chunk;
result = (Obj*)chunk;
index = freelistIndex(bytes);
mFreeList[index] = nextObj = (Obj*)(chunk + bytes);
for(i = 1; ; ++i)
{
currentObj = nextObj;
nextObj = (Obj*)((char*)nextObj + bytes);
if(nobjs-1 == i)
{
currentObj->next = 0;
break;
}
else
{
currentObj->next = nextObj;
}
}
return result;
}
char* Allocator::chunkAlloc(uint32_t size, int& nobjs)
{
char* result;
uint32_t totalBytes = size * nobjs;
uint32_t bytesLeft = mEndFree - mStartFree;
if(bytesLeft > totalBytes)
{
result = mStartFree;
mStartFree += totalBytes;
return result;
}
else if(bytesLeft > size)
{
nobjs = bytesLeft / size;
totalBytes = size * nobjs;
result = mStartFree;
mStartFree += totalBytes;
return result;
}
else
{
uint32_t bytesToGet = 2 * totalBytes + roundup(mHeapSize >> 4);
if(bytesLeft > 0)
{
uint32_t index = freelistIndex(bytesLeft);
((Obj*)(mStartFree))->next = mFreeList[index];
mFreeList[index] = (Obj*)mStartFree;
}
mStartFree = (char*)malloc(bytesToGet);
mHeapSize += bytesToGet;
mEndFree = mStartFree + bytesToGet;
return chunkAlloc(size, nobjs);
}
}
#ifndef CONSTRUCT_H
#define CONSTRUCT_H
#include <new>
template <class T>
inline void destroy(T* pointer)
{
pointer->~T();
}
template <class T>
inline void construct(T* p)
{
new (p) T();
}
template <class T, class T1>
inline void construct(T* p, const T1& a1)
{
new (p) T(a1);
}
template <class T, class T1, class T2>
inline void construct(T* p, const T1& a1, const T2& a2)
{
new (p) T(a1, a2);
}
template <class T, class T1, class T2, class T3>
inline void construct(T* p, const T1& a1, const T2& a2, const T3& a3)
{
new (p) T(a1, a2, a3);
}
template <class T, class T1, class T2, class T3, class T4>
inline void construct(T* p, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
{
new (p) T(a1, a2, a3, a4);
}
#endif
#ifndef NEW_H
#define NEW_H
#include "Allocator.h"
#include "Construct.h"
#define ALLOCATOR Allocator
template <class T>
class New
{
public:
typedef T Value;
typedef T* Point;
typedef T& Ref;
typedef ALLOCATOR Alloc;
public:
static Point allocate() {
Point obj = (Point)Alloc::allocate(sizeof(Value));
construct(obj);
return obj;
}
template <class T1>
static Point allocate(const T1& a1) {
Point obj = (Point)Alloc::allocate(sizeof(Value));
construct(obj, a1);
return obj;
}
template <class T1, class T2>
static Point allocate(const T1& a1, const T2& a2) {
Point obj = (Point)Alloc::allocate(sizeof(Value));
construct(obj, a1, a2);
return obj;
}
template <class T1, class T2, class T3>
static Point allocate(const T1& a1, const T2& a2, const T3& a3) {
Point obj = (Point)Alloc::allocate(sizeof(Value));
construct(obj, a1, a2, a3);
return obj;
}
template <class T1, class T2, class T3, class T4>
static Point allocate(const T1& a1, const T2& a2, const T3& a3, const T4& a4) {
Point obj = (Point)Alloc::allocate(sizeof(Value));
construct(obj, a1, a2, a3, a4);
return obj;
}
};
class Delete
{
public:
typedef ALLOCATOR Alloc;
template <class T1>
static void release(T1* point) {
destroy(point);
Alloc::deallocate(point, sizeof(T1));
}
};
#endif