您的位置:首页 > 移动开发

A wrapper of SGI STL memory allocator and deallocator

2008-03-08 09:01 477 查看
This article gives a wrapper of the SGI STL memory allocator and deallocator, providing a powerful tool for your own use directly. The header files needed are "alloc.h", "stl_config.h" and "stl_alloc.h". The last two are used within the library itself. We had better not use the memebers defined in them directly. Thus, If you are already using a C++ compiler supporting SGI STL, then just include "alloc.h" at the beginning of your files.

The allocator we are going to use is __default_alloc_template, which deals with small block allocation. It will check the requested size first. If it exceeds some given size, in SGI STL which is 128 bytes, it will call __malloc_alloc_template to deal with it. Our wrapper here, MemoryPool, is also designed with template parameters, in order to be general for all the cases. The following code shows how it is implemented.

//MemoryPool.h


#ifndef _MEMORY_POOL_H


#define _MEMORY_POOL_H




#include <cstddef>


// make sure that stl_config.h, stl_alloc.h and alloc.h


// can be seen by the compiler, and it is better to


// put them in the user's current directory


#include "alloc.h"




template <typename T>




class MemoryPool ...{


public:




MemoryPool() : obj_size(sizeof(T)), block_size(16) ...{}




~MemoryPool() ...{}


void * Alloc(size_t);


void Free(void *, size_t);


public:


size_t obj_size, block_size;


};




template <typename T>




void * MemoryPool<T>::Alloc(size_t size) ...{


return __default_alloc_template<false, 0>::allocate(size);


}




template <typename T>




void MemoryPool<T>::Free(void * dead, size_t size) ...{


__default_alloc_template<false, 0>::deallocate(dead, size);


}




#endif



The classes AirplaneWithPool and AirplaneReq are still used here.
//AirplaneWithPool.h


#ifndef _AIRPLANE_WITH_POOL_H


#define _AIRPLANE_WITH_POOL_H




#include "MemoryPool.h"


#include <cstddef>






class AirplaneReq ...{




};






class AirplaneWithPool ...{


public:


static void * operator new(size_t);


static void operator delete(void *, size_t);


public:


AirplaneReq * req;


static MemoryPool<AirplaneWithPool> mem_pool;


};




#endif



//AirplaneWithPool.cpp


#include "AirplaneWithPool.h"


#include "MemoryPool.h"




MemoryPool<AirplaneWithPool> AirplaneWithPool::mem_pool;






void * AirplaneWithPool::operator new(size_t size) ...{


return mem_pool.Alloc(size);


}






void AirplaneWithPool::operator delete(void * dead_object, size_t size) ...{


mem_pool.Free(dead_object, size);


}



//item10WithPool.cpp


#include "AirplaneWithPool.h"


#include <iostream>


using namespace std;






int main() ...{


#ifdef __STL_USE_NAMESPACES


cout << "malloc" << endl;


#else


cout << "default" << endl;


#endif




AirplaneWithPool * apwp0 = new AirplaneWithPool();


cout << "apwp0: " << apwp0 << endl;




AirplaneWithPool * apwp1 = new AirplaneWithPool();


cout << "apwp1: " << apwp1 << endl;




AirplaneWithPool * apwp2 = new AirplaneWithPool();


cout << "apwp2: " << apwp2 << endl;




delete apwp1;




AirplaneWithPool * apwp3 = new AirplaneWithPool();


cout << "apwp3: " << apwp3 << endl;




delete apwp3;




AirplaneWithPool * apwp4 = new AirplaneWithPool();


cout << "apwp4: " << apwp4 << endl;




return 0;


}



The running results are as below.
//printed in the terminal
default // this means that sgi stl defines __default_alloc_template as the default allocator
apwp0: 0x804b008
apwp1: 0x804b010
apwp2: 0x804b018
apwp3: 0x804b010
apwp4: 0x804b010

If your STL library is not this version, copy those two files to your working directory and make some slight modifications to make sure that the compiler will find them. In fact, every STL library provides the header file "alloc.h", with some public interfaces to use, but __default_alloc_template, may not be defined. It is the "private" member of SGI STL.

Let us modify the data member of class AirplaneWithPool. AirplaneReq * req is replaced with char data[256]. Then the running results are below.
//printed in the terminal
default
apwp0: 0x804b008
apwp1: 0x804b110
apwp2: 0x804b218
apwp3: 0x804b110
apwp4: 0x804b110

This is the condition that the memory block request exceeds 128 bytes. So __malloc_alloc_allocator is used to deal with it, which means malloc() is called directly. But, I don't know why there is always an 8-byte extra block (0x804b110 - 0x804b008 = 0x0000108, and it is 256 + 8). Maybe it is used for bookkeeping or just aligning. What do you think?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: