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(); }
相关文章推荐
- 理解C/C++中的allocator——(内存)分配器
- [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
- 关于 C++ 内存分配器
- C++ STL 容器自定义内存分配器
- C++ STL 容器自定义内存分配器
- [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
- [置顶] 从零开始学C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
- C++之STL(二):实现简单容器模板类Vec(vector capacity 增长问题、allocator 内存分配器)
- C++学习之STL的内存分配器
- 推荐一个跨平台内存分配器 - feixuwu - C++博客
- C++中的allocator类(内存分配器)
- c/c++中的内存分配器
- 摘录:一个由c/c++编译的程序占用的内存
- C++程序内存分配的问题
- C++中用vectors改进内存的再分配
- C++内存对象大会战
- [收藏]C++ Tips(7)--堆内存分配
- C/C++内存问题检查利器—Purify (五)
- C++内存对象大会战
- C++程序内存分配的问题