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 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
00034 #include <utility>
00035 #endif
00036
00037 #if __TBB_EXTRA_DEBUG
00038 #define __TBBMALLOC_ASSERT ASSERT
00039 #else
00040 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
00041 #endif
00042
00043 namespace tbb {
00044 namespace interface6 {
00046 namespace internal {
00047
00049 class pool_base : tbb::internal::no_copy {
00050
00051
00052 public:
00054 void recycle() { rml::pool_reset(my_pool); }
00055
00057 void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
00058
00060 void free(void* ptr) { rml::pool_free(my_pool, ptr); }
00061
00063
00064 void *realloc(void* ptr, size_t size) {
00065 return rml::pool_realloc(my_pool, ptr, size);
00066 }
00067
00068 protected:
00070 void destroy() { rml::pool_destroy(my_pool); }
00071
00072 rml::MemoryPool *my_pool;
00073 };
00074
00075 }
00077
00078 #if _MSC_VER && !defined(__INTEL_COMPILER)
00079
00080 #pragma warning (push)
00081 #pragma warning (disable: 4100)
00082 #endif
00083
00085
00086 template<typename T, typename P = internal::pool_base>
00087 class memory_pool_allocator {
00088 protected:
00089 typedef P pool_type;
00090 pool_type *my_pool;
00091 template<typename U, typename R>
00092 friend class memory_pool_allocator;
00093 template<typename V, typename U, typename R>
00094 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00095 template<typename V, typename U, typename R>
00096 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00097 public:
00098 typedef typename tbb::internal::allocator_type<T>::value_type value_type;
00099 typedef value_type* pointer;
00100 typedef const value_type* const_pointer;
00101 typedef value_type& reference;
00102 typedef const value_type& const_reference;
00103 typedef size_t size_type;
00104 typedef ptrdiff_t difference_type;
00105 template<typename U> struct rebind {
00106 typedef memory_pool_allocator<U, P> other;
00107 };
00108
00109 memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
00110 memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00111 template<typename U>
00112 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00113
00114 pointer address(reference x) const { return &x; }
00115 const_pointer address(const_reference x) const { return &x; }
00116
00118 pointer allocate( size_type n, const void* = 0) {
00119 return static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
00120 }
00122 void deallocate( pointer p, size_type ) {
00123 my_pool->free(p);
00124 }
00126 size_type max_size() const throw() {
00127 size_type max = static_cast<size_type>(-1) / sizeof (value_type);
00128 return (max > 0 ? max : 1);
00129 }
00131 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00132 template<typename... Args>
00133 void construct(pointer p, Args&&... args)
00134 #if __TBB_CPP11_STD_FORWARD_BROKEN
00135 { ::new((void *)p) T((args)...); }
00136 #else
00137 { ::new((void *)p) T(std::forward<Args>(args)...); }
00138 #endif
00139 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00140 void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); }
00141 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00142
00144 void destroy( pointer p ) { p->~value_type(); }
00145
00146 };
00147
00148 #if _MSC_VER && !defined(__INTEL_COMPILER)
00149 #pragma warning (pop)
00150 #endif // warning 4100 is back
00151
00153
00154 template<typename P>
00155 class memory_pool_allocator<void, P> {
00156 public:
00157 typedef P pool_type;
00158 typedef void* pointer;
00159 typedef const void* const_pointer;
00160 typedef void value_type;
00161 template<typename U> struct rebind {
00162 typedef memory_pool_allocator<U, P> other;
00163 };
00164
00165 memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
00166 memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00167 template<typename U>
00168 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00169
00170 protected:
00171 pool_type *my_pool;
00172 template<typename U, typename R>
00173 friend class memory_pool_allocator;
00174 template<typename V, typename U, typename R>
00175 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00176 template<typename V, typename U, typename R>
00177 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00178 };
00179
00180 template<typename T, typename U, typename P>
00181 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
00182
00183 template<typename T, typename U, typename P>
00184 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
00185
00186
00188 template <typename Alloc>
00189 class memory_pool : public internal::pool_base {
00190 Alloc my_alloc;
00191 static void *allocate_request(intptr_t pool_id, size_t & bytes);
00192 static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
00193
00194 public:
00196 memory_pool(const Alloc &src = Alloc());
00197
00199 ~memory_pool() { destroy(); }
00200
00201 };
00202
00203 class fixed_pool : public internal::pool_base {
00204 void *my_buffer;
00205 size_t my_size;
00206 inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
00207
00208 public:
00210 inline fixed_pool(void *buf, size_t size);
00212 ~fixed_pool() { destroy(); }
00213 };
00214
00216
00217 template <typename Alloc>
00218 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
00219 rml::MemPoolPolicy args(allocate_request, deallocate_request,
00220 sizeof(typename Alloc::value_type));
00221 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
00222 if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
00223 }
00224 template <typename Alloc>
00225 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
00226 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00227 const size_t unit_size = sizeof(typename Alloc::value_type);
00228 __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL);
00229 void *ptr;
00230 __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); }
00231 __TBB_CATCH(...) { return 0; }
00232 return ptr;
00233 }
00234 template <typename Alloc>
00235 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
00236 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00237 const size_t unit_size = sizeof(typename Alloc::value_type);
00238 __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL);
00239 self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
00240 return 0;
00241 }
00242 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
00243 rml::MemPoolPolicy args(allocate_request, 0, size, true);
00244 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
00245 if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
00246 }
00247 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
00248 fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
00249 if( !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) )
00250 return 0;
00251 return self.my_buffer;
00252 }
00253
00254 }
00255 using interface6::memory_pool_allocator;
00256 using interface6::memory_pool;
00257 using interface6::fixed_pool;
00258 }
00259
00260 #undef __TBBMALLOC_ASSERT
00261 #endif// __TBB_memory_pool_H