您的位置:首页 > 编程语言 > C语言/C++

c++内存分配器

2017-05-15 15:01 211 查看
#pragma once
/*
说明,此源文件内容由LJ类库轴抽取而来,
如有问题请QQ联系作者,QQ:511266323(W意波)(这是原作者的QQ)
加好友时请注明“BlockMemory"或者”LJ类库“字样
*/
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
#endif
namespace LJ
{

//同步操作相关,单次互斥对象
class MutexOnce
{
#ifdef WIN32
long mlock;
#else
pthread_mutex_t mutex;
#endif
MutexOnce(const MutexOnce&) {}
MutexOnce& operator=(const MutexOnce&) { return *(MutexOnce*)0; }
public:
MutexOnce();
~MutexOnce();
void Lock();
bool Try();
void UnLock();
void Reset();
};
#ifdef WIN32
inline MutexOnce::MutexOnce() :mlock(0) {}
inline void MutexOnce::Lock() {
for (;;) {
#ifdef InterlockedCompareExchangePointer
if (!InterlockedCompareExchange(&mlock, 1, 0))
return;
#else
if (!InterlockedCompareExchange((void**)&mlock, (void*)1, (void*)0))
return;
#endif
Sleep(0);
}
}
inline bool MutexOnce::Try()
{
#ifdef InterlockedCompareExchangePointer
return !InterlockedCompareExchange(&mlock, 1, 0);
#else
return !InterlockedCompareExchange((void**)&mlock, (void*)1, (void*)0);
#endif
}
inline void MutexOnce::UnLock()
{
InterlockedExchange(&mlock, 0);
}
inline MutexOnce::~MutexOnce() {}
inline void MutexOnce::Reset() { mlock = 0; }
#else
inline MutexOnce::MutexOnce() { pthread_mutex_init(&this->mutex, NULL); }
inline MutexOnce::~MutexOnce() { pthread_mutex_destroy(&this->mutex); }
inline void MutexOnce::Lock() { pthread_mutex_lock(&this->mutex); }
inline bool MutexOnce::Try() { return pthread_mutex_trylock(&this->mutex) == 0; }
inline void MutexOnce::UnLock() { pthread_mutex_unlock(&this->mutex); }
inline void MutexOnce::Reset() { pthread_mutex_destroy(&this->mutex); pthread_mutex_init(&this->mutex, NULL); }
#endif
//位操作相关内容
struct Bits
{
//获取i前导0的比特数(32位)
static int LeftZeroCount32(unsigned long i);
//获取i前导0的比特数(64位)
static int LeftZeroCount64(unsigned long long i);
//获取i前导0的比特数(自动匹配位数)
static int LeftZeroCount(unsigned long long i) { return LeftZeroCount64(i); }
//获取i前导0的比特数(自动匹配位数)
static int LeftZeroCount(unsigned long i) { return LeftZeroCount32(i); }
//获取i前导0的比特数(自动匹配位数)
static int LeftZeroCount(unsigned int i) { return LeftZeroCount32(i); }
};
inline int Bits::LeftZeroCount32(unsigned long z)
{
if (z > 0x0000ffff)
{
if (z > 0x00ffffff)
{
if (z > 0x0fffffff)
{
if (z > 0x3fffffff)
{
if (z > 0x7fffffff)return 0; return 1;
}   if (z > 0x1fffffff)return 2; return 3;
}   if (z > 0x03ffffff)
{
if (z > 0x07ffffff)return 4; return 5;
}   if (z > 0x01ffffff)return 6; return 7;
}   if (z > 0x000fffff)
{
if (z > 0x003fffff)
{
if (z > 0x007fffff)return 8; return 9;
}   if (z > 0x001fffff)return 10; return 11;
}   if (z > 0x0003ffff)
{
if (z > 0x0007ffff)return 12; return 13;
}   if (z > 0x0001ffff)return 14; retur
167c3
n 15;
}   if (z > 0x000000ff)
{
if (z > 0x00000fff)
{
if (z > 0x00003fff)
{
if (z > 0x00007fff)return 16; return 17;
}   if (z > 0x00001fff)return 18; return 19;
}   if (z > 0x000003ff)
{
if (z > 0x000007ff)return 20; return 21;
}   if (z > 0x000001ff)return 22; return 23;
}   if (z > 0x0000000f)
{
if (z > 0x0000003f)
{
if (z > 0x0000007f)return 24; return 25;
}   if (z > 0x0000001f)return 26; return 27;
}   if (z > 0x00000003)
{
if (z > 0x00000007)return 28; return 29;
}   if (z > 0x00000001)return 30; return z != 0 ? 31 : 32;
}
inline int Bits::LeftZeroCount64(unsigned long long i)
{
if (i < 0x0000000100000000)//很有意思的感觉,呵呵
{
if (i < 0x0000000000010000)
{
if (i < 0x0000000000000100)
{
if (i < 0x0000000000000010)
{
if (i < 0x0000000000000004)
{
if (i < 0x0000000000000002)return 64 - (int)i; return 62;
}   if (i < 0x0000000000000008)return 61; return 60;
}   if (i < 0x0000000000000040)
{
if (i < 0x0000000000000020)return 59; return 58;
}   if (i < 0x0000000000000080)return 57; return 56;
}   if (i < 0x0000000000001000)
{
if (i < 0x0000000000000400)
{
if (i < 0x0000000000000200)return 55; return 54;
}   if (i < 0x0000000000000800)return 53; return 52;
}   if (i < 0x0000000000004000)
{
if (i < 0x0000000000002000)return 51; return 50;
}   if (i < 0x0000000000008000)return 49; return 48;
}   if (i < 0x0000000001000000)
{
if (i < 0x0000000000100000)
{
if (i < 0x0000000000040000)
{
if (i < 0x0000000000020000)return 47; return 46;
}   if (i < 0x0000000000080000)return 45; return 44;
}   if (i < 0x0000000000400000)
{
if (i < 0x0000000000200000)return 43; return 42;
}   if (i < 0x0000000000800000)return 41; return 40;
}   if (i < 0x0000000010000000)
{
if (i < 0x0000000004000000)
{
if (i < 0x0000000002000000)return 39; return 38;
}   if (i < 0x0000000008000000)return 37; return 36;
}   if (i < 0x0000000040000000)
{
if (i < 0x0000000020000000)return 35; return 34;
}   if (i < 0x0000000080000000)return 33; return 32;
}   if (i < 0x0001000000000000)
{
if (i < 0x0000010000000000)
{
if (i < 0x0000001000000000)
{
if (i < 0x0000000400000000)
{
if (i < 0x0000000200000000)return 31; return 30;
}   if (i < 0x0000000800000000)return 29; return 28;
}   if (i < 0x0000004000000000)
{
if (i < 0x0000002000000000)return 27; return 26;
}   if (i < 0x0000008000000000)return 25; return 24;
}   if (i < 0x0000100000000000)
{
if (i < 0x0000040000000000)
{
if (i < 0x0000020000000000)return 23; return 22;
}   if (i < 0x0000080000000000)return 21; return 20;
}   if (i < 0x0000400000000000)
{
if (i < 0x0000200000000000)return 19; return 18;
}   if (i < 0x0000800000000000)return 17; return 16;
}   if (i < 0x0100000000000000)
{
if (i < 0x0010000000000000)
{
if (i < 0x0004000000000000)
{
if (i < 0x0002000000000000)return 15; return 14;
}   if (i < 0x0008000000000000)return 13; return 12;
}   if (i < 0x0040000000000000)
{
if (i < 0x0020000000000000)return 11; return 10;
}   if (i < 0x0080000000000000)return 9; return 8;
}   if (i < 0x1000000000000000)
{
if (i < 0x0400000000000000)
{
if (i < 0x0200000000000000)return 7; return 6;
}   if (i < 0x0800000000000000)return 5; return 4;
}   if (i < 0x4000000000000000)
{
if (i < 0x2000000000000000)return 3; return 2;
}   if (i < 0x8000000000000000)return 1; return 0;
}

//为了加速分配过程,节点将以size_t []动态数组的形式出现,BlockMemoryNode类提供操作size_t []数组节点的方法
//size_t p[]数组中内容安排:
//p[0]:已使用元素数
//p[1]:可用元素对应的位置数组记录索引
//p[2]:位置记录数组起始索引,数组元素数为iSize
//p[iSize+2]:内容数组起始索引,内容元素数为bSize
struct BlockMemoryNode
{
//将位置记录数组的index位置设置为相反的状态
static void set(size_t*p, size_t index)
{
p[index / (sizeof(size_t) * 8) + 2] ^= ((size_t)(1ull << (sizeof(size_t) * 8 - 1))) >> (index&(sizeof(size_t) * 8 - 1));
}
//获取一个可用的位置的指针并将该位置设置为不可用
static void*get(size_t*p, size_t iLen, size_t size)
{
size_t t = p[1];
size_t i = t;
iLen += 2;//iLen转换为终止位置索引
while (p[i] == 0)//i从2开始
{
if (++i == iLen)i = 2;
if (i == t)return (void*)NULL;
}
p[1] = i;
size_t tmp = (i - 2)*(sizeof(size_t) * 8) + Bits::LeftZeroCount(p[i]);
set(p, tmp);
++p[0];
return (unsigned char*)(p + iLen) + tmp*size;
}
//释放一个内存,成功返回true,size表示分配的块大小
template<size_t size>static bool free(void* pf, size_t*p, size_t iLen, size_t bLen)
{
size_t index = ((unsigned char*)pf - (unsigned char*)(p + 2 + iLen)) / size;
if (index >= bLen)
return false;
#ifdef _DEBUG
if (((p + 2)[index / (sizeof(size_t) * 8)]
& (((size_t)(1ull << (sizeof(size_t) * 8 - 1))) >> (index&(sizeof(size_t) * 8 - 1)))) != 0)
{
throw - 2;//抛出异常
}
#endif
size_t tmp = index;
set(p, tmp);
--p[0];
p[1] = tmp / (sizeof(size_t) * 8);
return true;
}
//获取一个内存,失败返回NULL
inline static void* alloc(size_t*p, size_t iLen, size_t size)
{
return get(p, iLen, size);
}
//初始化
static void Initial(size_t*p, size_t iLen, size_t bLen)
{
p[0] = p[1] = 0;
for (size_t i = 2; i < iLen + 2; ++i)p[i] = (size_t)-1;
size_t mov = (iLen * sizeof(size_t) * 8 - bLen);
p[iLen + 1] <<= mov;
}
static size_t GetIndexLen(size_t bLen)
{
return (bLen + sizeof(size_t) * 8 - 1) / (sizeof(size_t) * 8);
}
static size_t GetBlockLen(size_t bufferLength, size_t size)
{
size_t result = ((bufferLength - 2) * sizeof(size_t) * 8) / (size * 8 + 2);
while (((result + 1) * sizeof(size_t) * 8 - 1) / (sizeof(size_t) * 8) + (size*result + sizeof(size_t) - 1) / (sizeof(size_t) * 8) > bufferLength - 2)--result;
return result;
}
};
//块内存对象,用以分配块大小为size字节大小的内存
template<size_t size>class BlockMemory
{
//节点数组,检索以分配内存(升序排列)
size_t** pArr;
//数组大小
size_t arrSize;
//互斥对象
MutexOnce mtStatic;
//节点总数
size_t NodeCount;
//已用节点数
size_t UsedCount;
//上次有内容节点号
size_t TmpIndex;
//索引数组长度
size_t IndexLength;
//元素数组长度
size_t BlockLength;
//节点大小
size_t BufferLength;
//增加新节点
void AddNode(size_t*);
//禁止复制和赋值
BlockMemory(BlockMemory const&) {}
BlockMemory&operator=(BlockMemory const&) {}
public:
//构造函数,参数enableMutex用以指定是否进行多线程同步,参数bufferLength用以指定节点大小(以size_t为单位)
//注意:块大小在对象生成后需要释放所有内存才能修改
BlockMemory(bool enableMutex = true, size_t bufferLength = 65536 / sizeof(size_t) - 8);
//析构函数
~BlockMemory() { RemoveAll(); }
//是否启用多线程同步(默认使用)
bool EnableMutex;
//返回一个指针指向一个StructOfSize<size>对象(size字节大小)
void* Alloc();
//释放Alloc所分配的内存
void Free(void*p);
//移除未使用的节点
void RemoveEmpty();
//移除所有节点(如果有内存未释放将抛出异常)
void RemoveAll();
//修改块大小,(以size_t为元素的数组元素数)
void ChangeBufferSize(size_t bufferLength);
//获取当前块大小
size_t GetBufferSize() { return BufferLength; }
};
template<size_t size>void BlockMemory<size>::AddNode(size_t*p)
{
if (pArr == NULL)
{
pArr = (size_t**)malloc(4 * sizeof(size_t*));
arrSize = 4;
*pArr = p;
TmpIndex = 0;
}
else
{
if (NodeCount == arrSize)
{
++arrSize;
void* pp = realloc(pArr, arrSize * sizeof(size_t*));
if (pp == 0)throw - 3;//申请内存失败
pArr = (size_t**)pp;
}
if (p > pArr[NodeCount - 1])
{
pArr[TmpIndex = NodeCount] = p;
}
else if (p < pArr[0])
{
for (size_t i = NodeCount; i > 0; --i)
{
pArr[i] = pArr[i - 1];
}
pArr[0] = p;
TmpIndex = 0;
}
else
{
size_t high = NodeCount - 1;
size_t low = 1;
size_t current = NodeCount / 2;
for (;;)
{
if (pArr[current]>p)
{
high = current;
if (pArr[current - 1] < p)break;
size_t tmp = (low + current) / 2;
if (current == tmp)
{
--current;
}
else current = tmp;
}
else if (pArr[current] < p)
{
low = current;
size_t tmp = (current + high) / 2;
if (current == tmp)
{
++current;
}
else current = tmp;
}
else break;
}
for (size_t i = NodeCount; i>current; --i)
{
pArr[i] = pArr[i - 1];
}
pArr[current] = p;
TmpIndex = current;
}
}
++NodeCount;
}
template<size_t size>BlockMemory<size>::BlockMemory(bool enableMutex, size_t bufferLength)
:BufferLength(bufferLength), pArr(NULL), UsedCount(0), TmpIndex(0), arrSize(0), NodeCount(0), EnableMutex(enableMutex)
{
BlockLength = BlockMemoryNode::GetBlockLen(bufferLength, size);
IndexLength = BlockMemoryNode::GetIndexLen(BlockLength);
}
template<size_t size>void* BlockMemory<size>::Alloc()
{
void*p;
if (EnableMutex)mtStatic.Lock();
size_t i = NodeCount - 1;
if (UsedCount == NodeCount)
{
size_t* t = (size_t*)malloc(BufferLength * sizeof(size_t));
BlockMemoryNode::Initial(t, IndexLength, BlockLength);
p = BlockMemoryNode::alloc(t, IndexLength, size);
AddNode(t);
}
else
{
size_t t = TmpIndex;
if (pArr[t][0] == BlockLength)
{
for (;;)
{
if (++t == NodeCount)t = 0;
if (pArr[t][0] != BlockLength)break;
}
TmpIndex = t;
}
p = BlockMemoryNode::alloc(pArr[t], IndexLength, size);
if (pArr[t][0] == BlockLength)
UsedCount++;
}
if (EnableMutex)mtStatic.UnLock();
return p;
}
template<size_t size>void BlockMemory<size>::Free(void*p)
{
if (!p)return;
if (EnableMutex)mtStatic.Lock();
if (pArr)
{
if (NodeCount == 1 || pArr[1] > p)
{
TmpIndex = 0;
if (BlockMemoryNode::free<size>(p, pArr[0], IndexLength, BlockLength) && pArr[0][0] == BlockLength - 1)UsedCount--;
}
else if (pArr[NodeCount - 1] < p)
{
TmpIndex = NodeCount - 1;
if (BlockMemoryNode::free<size>(p, pArr[NodeCount - 1], IndexLength, BlockLength) && pArr[NodeCount - 1][0] == BlockLength - 1)UsedCount--;
}
else//二分法查找
{
size_t high = NodeCount - 1;
size_t low = 0;
size_t current = high / 2;
for (;;)
{
if (pArr[current]>p)
{
high = current;
size_t tmp = (low + current) / 2;
if (current == tmp)
--current;
else current = tmp;
}
else if (pArr[current + 1] < p)
{
low = current;
size_t tmp = (current + high) / 2;
if (current == tmp)
{
if (pArr[current + 1]>p)break;
++current;
}
else current = tmp;
}
else break;
}
if (BlockMemoryNode::free<size>(p, pArr[current], IndexLength, BlockLength) && pArr[current][0] == BlockLength - 1)UsedCount--;
TmpIndex = current;
}
}
if (EnableMutex)mtStatic.UnLock();
}
template<size_t size>void BlockMemory<size>::RemoveEmpty()
{
if (EnableMutex)mtStatic.Lock();
for (size_t t = 0, lt = 0; lt < NodeCount; ++lt)
{
pArr[t] = pArr[lt];
if (pArr[t][0] == 0)
{
free(pArr[t]);
if (TmpIndex == t)TmpIndex = 0;
else if (TmpIndex>t)--TmpIndex;
--NodeCount;
}
else ++t;
}
if (EnableMutex)mtStatic.UnLock();
}
template<size_t size>void BlockMemory<size>::RemoveAll()
{
if (EnableMutex)mtStatic.Lock();
if (UsedCount != 0)
{
if (EnableMutex)mtStatic.UnLock();
throw - 1;//有部分内容未释放
}
for (size_t t = 0; t < NodeCount; ++t)
{
free(pArr[t]);
}
free(pArr);
pArr = NULL;
NodeCount = 0;
arrSize = 0;
if (EnableMutex)mtStatic.UnLock();
}
template<size_t size>void BlockMemory<size>::ChangeBufferSize(size_t bufferLength)
{
RemoveAll();
BlockLength = BlockMemoryNode::GetBlockLen(bufferLength, size);
IndexLength = BlockMemoryNode::GetIndexLen(BlockLength);
}
}


// myMalloc.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "myMalloc.h"
using namespace LJ;
void* p[10000000];
int main()
{
//简单测试程序(块大小为123字节)
BlockMemory<128> mc;
//申请内存
for (size_t i = 0; i < 10000000; ++i)
{
p[i] = mc.Alloc();
}
//释放内存
for (size_t i = 0; i < 10000000; ++i)
{
mc.Free(p[i]);
}
//移除所有占用内存
mc.RemoveAll();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  内存分配器