src/Utility/Collection/pool/pool_allocator.h

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 //
00033 // Pool allocator which is compatible with STL collection class.
00034 // This allocator never free memory and corrupt in multi-thread.
00035 //
00036 
00037 #ifndef __ONIKIRI_POOL_H
00038 #define __ONIKIRI_POOL_H
00039 
00040 #include <stack>
00041 #include <vector>
00042 
00043 //#define ONIKIRI_POOL_ALLOCATOR_INVESTIGATE
00044 
00045 namespace Onikiri
00046 {
00047     static const int POOL_ALLOCATOR_CHUNK_SIZE_BASE = 64;
00048 
00049     template <typename T>
00050     class pool_body
00051     {
00052     public:
00053         typedef T                  value_type;
00054         typedef value_type*        pointer;
00055         typedef value_type&        reference;
00056         typedef const value_type*  const_pointer;
00057         typedef const value_type&  const_reference;
00058         typedef size_t             size_type;
00059         typedef ptrdiff_t          difference_type;
00060 
00061     protected:  
00062 
00063         template <typename U>
00064         class pool_stack
00065         {
00066             std::vector<U> stack_body;
00067             size_t stack_top;
00068         public:
00069 
00070             pool_stack() : 
00071                 stack_body(POOL_ALLOCATOR_CHUNK_SIZE_BASE),
00072                 stack_top(0)
00073             {
00074             };
00075 
00076             void push(const U& v)
00077             {
00078                 if(stack_body.size() <= stack_top){
00079                     stack_body.resize(stack_body.size()*2);
00080                 }
00081                 stack_body[stack_top] = v;
00082                 stack_top++;
00083             }
00084 
00085             void pop()
00086             {
00087                 stack_top--;
00088             }
00089 
00090             U& top()
00091             {
00092                 assert(stack_top != 0);
00093                 return stack_body[stack_top - 1];
00094             }
00095 
00096             size_t size()
00097             {
00098                 return stack_top;
00099             }
00100         };
00101 
00102         //typedef std::stack<T*>   stack_type;
00103         typedef pool_stack<T*>     stack_type;
00104         std::vector< stack_type* > ptr_stack_array;
00105         std::vector<T*> ptr_list;
00106 
00107     #ifdef ONIKIRI_POOL_ALLOCATOR_INVESTIGATE
00108         size_t total_memory;
00109         size_t total_count;
00110         std::vector<size_t> total_memory_array;
00111         std::vector<size_t> total_count_array;
00112     #endif
00113         void allocate_chank( size_type count, stack_type* stack )
00114         {
00115             size_t chunk_size = POOL_ALLOCATOR_CHUNK_SIZE_BASE / count;
00116             if(chunk_size < 4)
00117                 chunk_size = 4;
00118 
00119             // Throw std::bad_alloc if memory allocation failed.
00120             pointer chunk = (pointer)( ::operator new(chunk_size * count * sizeof(T)) );
00121             ptr_list.push_back(chunk);
00122 
00123             for( size_t i = 0; i < chunk_size; i++){
00124                 stack->push( chunk );
00125                 chunk += count;
00126             }
00127 
00128         #ifdef ONIKIRI_POOL_ALLOCATOR_INVESTIGATE
00129             total_memory += chunk_size * count * sizeof(T);
00130             total_count  += chunk_size * count;
00131             if( total_memory_array.size() <= count ){
00132                 total_memory_array.resize( count + 1 );
00133                 total_count_array.resize( count + 1 );
00134             }
00135             total_memory_array[count] += chunk_size * count * sizeof(T);
00136             total_count_array[count] += chunk_size * count;
00137         #endif
00138         }
00139 
00140     public:
00141 
00142         pool_body()
00143         {
00144         };
00145 
00146         ~pool_body()
00147         {
00148             for(size_t i = 0; i < ptr_list.size(); i++){
00149                 ::operator delete( (void*)ptr_list[i] );
00150             }
00151             for(size_t i = 0; i < ptr_stack_array.size(); i++){
00152                 if(ptr_stack_array[i]){
00153                     delete ptr_stack_array[i];
00154                 }
00155             }
00156         #ifdef ONIKIRI_POOL_ALLOCATOR_INVESTIGATE
00157             printf( "pool_allocator< %s > : \n\ttype size : %d bytes\n\ttotal : %d bytes, %d elements\n", typeid(T).name(), (int)sizeof(T), (int)total_memory, (int)total_count );
00158             for( size_t i = 0; i < total_memory_array.size(); i++ ){
00159                 if( total_memory_array[i] > 0)
00160                     printf("\t%d : %d bytes, %d elements\n", (int)i, (int)total_memory_array[i], (int)total_count_array[i] );
00161             }
00162         #endif
00163         };
00164 
00165         INLINE pointer allocate(
00166             size_type count, 
00167             const void* hint = 0)
00168         {
00169             if(count == 0)
00170                 return 0;
00171 
00172             if(ptr_stack_array.size() <= count){
00173                 ptr_stack_array.resize(count+1, 0);
00174             }
00175 
00176             stack_type* stack = ptr_stack_array[count];
00177             if(stack == 0){
00178                 // Throw std::bad_alloc if memory allocation failed.
00179                 stack = new stack_type();
00180                 ptr_stack_array[count] = stack;
00181             }
00182             
00183             // Allocate memory chunk
00184             if(stack->size() == 0){
00185                 allocate_chank( count, stack );
00186             }
00187 
00188             pointer ptr = stack->top();
00189             stack->pop();
00190             return ptr;
00191         }
00192 
00193         INLINE void deallocate(pointer ptr, size_type count)
00194         {
00195             stack_type* stack = ptr_stack_array[count];
00196             stack->push(ptr);
00197         }   
00198     };
00199 
00200     template <typename T>
00201     class pool_allocator
00202     {
00203         typedef pool_body<T> pool_type;
00204         INLINE pool_type& pool()
00205         {
00206             static pool_type p;
00207             return p;
00208         }
00209 
00210     public:
00211 
00212         typedef T                  value_type;
00213         typedef value_type*        pointer;
00214         typedef value_type&        reference;
00215         typedef const value_type*  const_pointer;
00216         typedef const value_type&  const_reference;
00217         typedef size_t             size_type;
00218         typedef ptrdiff_t          difference_type;
00219 
00220         template <class U>
00221         struct rebind
00222         {
00223             typedef pool_allocator<U> other;
00224         };
00225 
00226         pool_allocator()
00227         {
00228         }
00229 
00230         pool_allocator(const pool_allocator&)
00231         {
00232         }
00233 
00234         template <class U> 
00235         pool_allocator(const pool_allocator<U>&)
00236         {
00237         }
00238 
00239         ~pool_allocator()
00240         {
00241         }
00242 
00243         INLINE pointer allocate(
00244             size_type count, 
00245             const void* hint = 0)
00246         {
00247             return pool().allocate(count);
00248 
00249         }
00250 
00251         INLINE void construct(pointer ptr, const T& value)
00252         {
00253             new (ptr) T(value);
00254         }
00255 
00256         INLINE void deallocate(pointer ptr, size_type count)
00257         {
00258             return pool().deallocate(ptr, count);
00259         }
00260 
00261         INLINE void destroy(pointer ptr)
00262         {
00263             ptr->~T();
00264         }
00265 
00266         pointer address(reference value) const 
00267         {
00268             return &value; 
00269         }
00270 
00271         const_pointer address(const_reference value) const 
00272         {
00273             return &value; 
00274         }
00275 
00276         size_type max_size() const
00277         {
00278             return std::numeric_limits<size_t>::max() / sizeof(T);
00279         }
00280     };
00281 
00282 
00283     template <class T1, class T2>
00284     bool operator==(const pool_allocator<T1>&, const pool_allocator<T2>&) 
00285     {
00286         return true; 
00287     }
00288 
00289     template <class T1, class T2>
00290     bool operator!=(const pool_allocator<T1>&, const pool_allocator<T2>&) 
00291     {
00292         return false; 
00293     }
00294 
00295 };  // namespace Onikiri
00296 
00297 #endif
00298 

Onikiri2に対してTue Jun 18 14:34:27 2013に生成されました。  doxygen 1.4.7