为C++标准库容器写自己的内存分配程序
根据sgi 的STL源码的二级分配算法改写的内存池分配程序,只要稍微修改就可以实现共享内存方式管理,使用C++标准库容器中的map,set,multimap,multiset测试通过,vector测试通不过,原因是在内存回收的时候考虑的比较简单,vector每次分配内存个数不固定,回收也不固定,这样的话,程序还需要继续完善。Z{:L2b&x%f{o?C
内存池管理程序源码如下:'G4E7if#X @-v
以下是引用片段:[Cob0O Xs
#ifndef MY_ALLOCATOR_H_ !iS*J]$T
#define MY_ALLOCATOR_H_
#include "stdafx.h" CQ@G$t/vE5F;J.l
#include <limits> ?c]+S-ly
#include <iostream> l$k(dbL[-IF*D%J
namespace happyever
{ R/QfGjl,F9g
enum { NODENUMS = 2 };
union _Obj
{ Yb+F$T4s~
union _Obj* M_free_list_link; h,g$T O7k|'d\
char M_client_data[1]; c,g I3@M N7Hz
} ;
typedef union _Obj Obj;
struct _Cookie
{ 2i$xmaF.\*n8i
int iShmKey; /* 共享内存键值 */
int iShmID; /* iShmKey对应的shmid */ xL,y0|*R9U
int iSemKey; /* 锁信号键值 */
int iSemID; /* 锁信号标识 */
int iTotalsize; /* 容器总容量 */ o+qTA2k#t
void* pStartall; /* 共享内存自身地址 */ I7L'X0d0b0i f
char* pStartfree; /* 自由空间的开始地址*/
char* pEndfree; /* 自由空间的结束地址*/ g Q:XxdsYlT
int iUseNum[NODENUMS]; w6MK B@)je
/*用来存放free_list中节点的size*/ .hGO3l*_:j
short sFreelistIndex[NODENUMS];
/*存放分配内存节点的链表*/ sp!J w\R
Obj* uFreelist[NODENUMS];
};
typedef struct _Cookie Cookie; (KL| Z m1Z
//Obj; &q2B,k?H8|(C-e
//Cookie; q$?CrW
static Cookie *pHead = NULL;
template <class T>
class MyAlloc -~/c7H2fT3Veq\
{
private: #R'FI/](_CH^ b!o`)y
static const int ALIGN = sizeof(Obj); WK|x/lx`u+YN'S b
int round_up(int bytes);
int freelist_index(int bytes);
int freelist_getindex(int bytes);
char* chunk_alloc(int size, int *nobjs); 1dnB6u q+a)K
void* refill(int num,int n);
public:
// type definitions
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference; wM9b9M%\
typedef const T& const_reference; n._SIb)l
typedef std::size_t size_type; ~$XHE1i B-P*h~V
typedef std::ptrdiff_t difference_type; -G| Hx"^zo
template <class U>
struct rebind
{
typedef MyAlloc<U> other; $I{!p4p FF
}; 3]4uzs-X"t6Ev
pointer address (reference value) const
{
return &value;
}
const_pointer address (const_reference value) const
{ 4c^NCY:|&E_h.^
return &value; k&HLKWTQ;?K5H
}
MyAlloc() throw()
{ i4}Dh1X \
std::cout<<"MyAlloc"<<std::endl; "A)K3f9y0^7t(r"C
}
MyAlloc(const MyAlloc& x) throw() $alRs7p
{ _n0V.@ d']k
std::cout<<"const MyAlloc"<<std::endl; -v:Q @AzyTN3T
}
template <class U> +f&ZMi}
MyAlloc (const MyAlloc<U>& x) throw() BrKL j.^gJ
{
std::cout<<"const MyAlloc<U>"<<std::endl; 0Jj)@lt
} \LfP(p6JQ
~MyAlloc() throw() QVYIq!ui1N
{ |%sfaa6`5m(L9T
std::cout<<"~MyAlloc"<<std::endl;
} T| }K _ T1E
size_type max_size () const throw()
{ ovU`Q:c
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
//void PrintFreelistAndCookie(); 3oa1Q.}/YZ"hh0q+X1l
pointer allocate (size_type num, const void* = 0)
{
pointer ret = 0;
Obj** my_free_list; n1k[:U_@B
Obj* result;
int index; 0A3p!HX5Fw7E2_:c!|a
// print message and allocate memory with global new
std::cerr << "allocate " << num << " element(s)"
<< " of size " << sizeof(T) << std::endl; 3Id C/c8]5gk~s\
index = freelist_index(sizeof(T));
if(index >= NODENUMS)
{
return NULL;
}
my_free_list = pHead->uFreelist + index;
//Lock(semid,LOCK_NUM); '\QD5W Ebwrzh
result = *my_free_list; [&mi?Wb
if (result == 0) ^.a$w@yh
{
ret = (pointer)refill((int)num, round_up(sizeof(T)));
} s \)e.b)U:HBk+k;\n
else
{
*my_free_list = result->M_free_list_link;
ret = (pointer)result;
} 2N5` ^'L6V'u0uh OG
//UnLock(semid,LOCK_NUM); I:s8W%a@u*W/H
pHead->iUseNum[index] = pHead->iUseNum[index] + (int)num; /?:X{hKY$g6[ h7L
if(0 == ret)
{ "} \-Vij4R(C
std::cerr << "alloc memory fail!" << std::endl;
exit(1);
}
std::cerr << " allocated at: " << (void*)ret << std::endl;
PrintFreelistAndCookie(); l/po;Q[ @ z*R O
return ret; %LL&a3L#|DK}F
}
void construct (pointer p, const T& value)
{ ,N Eb s4Z_
// initialize memory with placement new B'uT3Pr9A F&b#in
new((void*)p)T(value); 6\?aU/R%z
}
void destroy (pointer p)
{ /e(}"dPK&W]Q
// destroy objects by calling their destructor 0\ Lw f&F?7z
p->~T(); bBelL.UFQ$r
} 8K1r%z La$}W}N
void deallocate (pointer p, size_type num)
{
Obj** my_free_list;
Obj* q ;
int index; 9o7AH B yr?!]3e
index = freelist_getindex(sizeof(T));
if(index >= NODENUMS)
{
std::cerr << "deallocate memory fail!" << std::endl;
exit(1); Y2XbV1xN-~!u-{K
}
my_free_list = pHead->uFreelist + index;
q = (Obj*) p; ]b6fo7^Y"P
//Lock(semid,LOCK_NUM);
/*这个地方可能会有问题*/ UR`po}z
//for(int i=0 ;i<(int)num ; i++)
{ 5ZA}ODX&B
q->M_free_list_link = *my_free_list;
*my_free_list = q;
}
//UnLock(semid,LOCK_NUM); X}he(M,u
pHead->iUseNum[index] = pHead->iUseNum[index] - (int)num;
std::cerr << "deallocate " << num << " element(s)"
<< " of size " << sizeof(T)
<< " at: " << (void*)p << std::endl; jF)vZ4N5I5bLe
PrintFreelistAndCookie(); "Ep{"K%kGw0h:R$O%f
}
};
template <class T> iv5w m\K3|{ V4D"n
int MyAlloc<T>::round_up(int bytes)
{
int i;
i = bytes;
if(bytes < ALIGN) I`PK[
{ [*Xq|[ jF6T
i = ALIGN; K3P4EX"EQ
}
std::cout<<"round_up:bytes="<<bytes<<" , return="<<i<<std::endl;
return i; 7yt#x'[ox
}; yFvmq*H\S&n3_,_
template <class T> H {6W9w#R
int MyAlloc<T>::freelist_index(int bytes)
{ *u:k(@Qy"Z)XJy
int i; o [+I;jw H-md4S
for(i=0 ; i< NODENUMS ; i++) q*p~[*D/x0N@y
{ w/_eK}iT
if(pHead->sFreelistIndex[i] == bytes)
break;
} R2Fg)T"[
if(i >= NODENUMS) 9E!U| V ]
{
for(i=0 ; i< NODENUMS ; i++) B5u4]"v2g:XqB
{ ,L(dqW:\%D9H}J
if(pHead->sFreelistIndex[i] == 0) E_.I,Ei_
{ /a:q*Ui7tfqD
pHead->sFreelistIndex[i] = bytes; E D9k8q/~:l d+H|
std::cout<<"freelist_index:bytes="<<bytes<<" , return="<<i<<std::endl; z)M5B#x!Q
return i; ,\1c/g6k {3^
} 2aJN ufNW
} 8mh(y~Q$Ha
}