memory_pool.h

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2011 Intel Corporation.  All Rights Reserved.
00003 
00004     The source code contained or described herein and all documents related
00005     to the source code ("Material") are owned by Intel Corporation or its
00006     suppliers or licensors.  Title to the Material remains with Intel
00007     Corporation or its suppliers and licensors.  The Material is protected
00008     by worldwide copyright laws and treaty provisions.  No part of the
00009     Material may be used, copied, reproduced, modified, published, uploaded,
00010     posted, transmitted, distributed, or disclosed in any way without
00011     Intel's prior express written permission.
00012 
00013     No license under any patent, copyright, trade secret or other
00014     intellectual property right is granted to or conferred upon you by
00015     disclosure or delivery of the Materials, either expressly, by
00016     implication, inducement, estoppel or otherwise.  Any license under such
00017     intellectual property rights must be express and approved by Intel in
00018     writing.
00019 */
00020 
00021 #ifndef __TBB_memory_pool_H
00022 #define __TBB_memory_pool_H
00023 
00024 #if !TBB_PREVIEW_MEMORY_POOL
00025 #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h
00026 #endif
00027 
00029 #include "scalable_allocator.h"
00030 #include "tbb_stddef.h"
00031 #include "tbb_machine.h" // TODO: Itanium requires linkage with TBB library
00032 #include <new> // std::bad_alloc
00033 
00034 #if __TBB_EXTRA_DEBUG
00035 #define __TBBMALLOC_ASSERT ASSERT
00036 #else
00037 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
00038 #endif
00039 
00040 namespace tbb {
00041 namespace interface6 {
00043 namespace internal {
00044 
00046 class pool_base : tbb::internal::no_copy {
00047     // Pool interface is separate from standard allocator classes because it has
00048     // to maintain internal state, no copy or assignment. Move and swap are possible.
00049 public:
00051     void recycle() { rml::pool_reset(my_pool); }
00052 
00054     void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
00055 
00057     void free(void* ptr) { rml::pool_free(my_pool, ptr); }
00058 
00060     // Enables some low-level optimization possibilities
00061     void *realloc(void* ptr, size_t size) {
00062         return rml::pool_realloc(my_pool, ptr, size);
00063     }
00064 
00065 protected:
00067     void destroy() { rml::pool_destroy(my_pool); }
00068 
00069     rml::MemoryPool *my_pool;
00070 };
00071 
00072 } // namespace internal
00074 
00075 #if _MSC_VER && !defined(__INTEL_COMPILER)
00076     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
00077     #pragma warning (push)
00078     #pragma warning (disable: 4100)
00079 #endif
00080 
00082 
00083 template<typename T, typename P = internal::pool_base>
00084 class memory_pool_allocator {
00085 protected:
00086     typedef P pool_type;
00087     pool_type *my_pool;
00088     template<typename U, typename R>
00089     friend class memory_pool_allocator;
00090     template<typename V, typename U, typename R>
00091     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00092     template<typename V, typename U, typename R>
00093     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00094 public:
00095     typedef typename tbb::internal::allocator_type<T>::value_type value_type;
00096     typedef value_type* pointer;
00097     typedef const value_type* const_pointer;
00098     typedef value_type& reference;
00099     typedef const value_type& const_reference;
00100     typedef size_t size_type;
00101     typedef ptrdiff_t difference_type;
00102     template<typename U> struct rebind {
00103         typedef memory_pool_allocator<U, P> other;
00104     };
00105 
00106     memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
00107     memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00108     template<typename U>
00109     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00110 
00111     pointer address(reference x) const { return &x; }
00112     const_pointer address(const_reference x) const { return &x; }
00113     
00115     pointer allocate( size_type n, const void* /*hint*/ = 0) {
00116         return static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
00117     }
00119     void deallocate( pointer p, size_type ) {
00120         my_pool->free(p);
00121     }
00123     size_type max_size() const throw() {
00124         size_type max = static_cast<size_type>(-1) / sizeof (value_type);
00125         return (max > 0 ? max : 1);
00126     }
00128     void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); }
00129 
00131     void destroy( pointer p ) { p->~value_type(); }
00132 
00133 };
00134 
00135 #if _MSC_VER && !defined(__INTEL_COMPILER)
00136     #pragma warning (pop)
00137 #endif // warning 4100 is back
00138 
00140 
00141 template<typename P> 
00142 class memory_pool_allocator<void, P> {
00143 public:
00144     typedef P pool_type;
00145     typedef void* pointer;
00146     typedef const void* const_pointer;
00147     typedef void value_type;
00148     template<typename U> struct rebind {
00149         typedef memory_pool_allocator<U, P> other;
00150     };
00151 
00152     memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
00153     memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00154     template<typename U>
00155     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00156 
00157 protected:
00158     pool_type *my_pool;
00159     template<typename U, typename R>
00160     friend class memory_pool_allocator;
00161     template<typename V, typename U, typename R>
00162     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00163     template<typename V, typename U, typename R>
00164     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00165 };
00166 
00167 template<typename T, typename U, typename P>
00168 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
00169 
00170 template<typename T, typename U, typename P>
00171 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
00172 
00173 
00175 template <typename Alloc>
00176 class memory_pool : public internal::pool_base {
00177     Alloc my_alloc; // TODO: base-class optimization
00178     static void *allocate_request(intptr_t pool_id, size_t & bytes);
00179     static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
00180 
00181 public:
00183     memory_pool(const Alloc &src = Alloc());
00184 
00186     ~memory_pool() { destroy(); } // call the callbacks first and destroy my_alloc latter
00187 
00188 };
00189 
00190 class fixed_pool : public internal::pool_base {
00191     void *my_buffer;
00192     size_t my_size;
00193     inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
00194 
00195 public:
00197     inline fixed_pool(void *buf, size_t size);
00199     ~fixed_pool() { destroy(); }
00200 };
00201 
00203 
00204 template <typename Alloc>
00205 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
00206     rml::MemPoolPolicy args = {
00207         allocate_request, deallocate_request, sizeof(typename Alloc::value_type)
00208     };
00209     my_pool = rml::pool_create(intptr_t(this), &args);
00210     __TBBMALLOC_ASSERT(my_pool, "Pool is not created");
00211     if( !my_pool ) __TBB_THROW(std::bad_alloc());
00212 }
00213 template <typename Alloc>
00214 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
00215     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00216     const size_t unit_size = sizeof(typename Alloc::value_type);
00217     __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL);
00218     void *ptr;
00219     __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); }
00220     __TBB_CATCH(...) { return 0; }
00221     return ptr;
00222 }
00223 template <typename Alloc>
00224 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
00225     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00226     const size_t unit_size = sizeof(typename Alloc::value_type);
00227     __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL);
00228     self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
00229     return 0;
00230 }
00231 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
00232     rml::MemPoolPolicy args = { allocate_request, 0, size };
00233     my_pool = rml::pool_create(intptr_t(this), &args);
00234     __TBBMALLOC_ASSERT(my_pool, "Pool is not created");
00235     if( !my_pool ) __TBB_THROW(std::bad_alloc());
00236 }
00237 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
00238     fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
00239     if( bytes > self.my_size || !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) )
00240         return 0; // all the memory was given already
00241     return self.my_buffer;
00242 }
00243 
00244 } //namespace interface6
00245 using interface6::memory_pool_allocator;
00246 using interface6::memory_pool;
00247 using interface6::fixed_pool;
00248 } //namespace tbb
00249 
00250 #undef __TBBMALLOC_ASSERT
00251 #endif// __TBB_memory_pool_H

Copyright © 2005-2011 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.