00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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"
00032 #include <new>
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
00048
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
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 }
00074
00075 #if _MSC_VER && !defined(__INTEL_COMPILER)
00076
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* = 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;
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(); }
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;
00241 return self.my_buffer;
00242 }
00243
00244 }
00245 using interface6::memory_pool_allocator;
00246 using interface6::memory_pool;
00247 using interface6::fixed_pool;
00248 }
00249
00250 #undef __TBBMALLOC_ASSERT
00251 #endif// __TBB_memory_pool_H