00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __TBB_memory_pool_H
00030 #define __TBB_memory_pool_H
00031
00032 #if !TBB_PREVIEW_MEMORY_POOL
00033 #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h
00034 #endif
00035
00037 #include "scalable_allocator.h"
00038 #include "tbb_stddef.h"
00039 #include "tbb_machine.h"
00040 #include <new>
00041 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
00042 #include <utility>
00043 #endif
00044
00045 #if __TBB_EXTRA_DEBUG
00046 #define __TBBMALLOC_ASSERT ASSERT
00047 #else
00048 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
00049 #endif
00050
00051 namespace tbb {
00052 namespace interface6 {
00054 namespace internal {
00055
00057 class pool_base : tbb::internal::no_copy {
00058
00059
00060 public:
00062 void recycle() { rml::pool_reset(my_pool); }
00063
00065 void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
00066
00068 void free(void* ptr) { rml::pool_free(my_pool, ptr); }
00069
00071
00072 void *realloc(void* ptr, size_t size) {
00073 return rml::pool_realloc(my_pool, ptr, size);
00074 }
00075
00076 protected:
00078 void destroy() { rml::pool_destroy(my_pool); }
00079
00080 rml::MemoryPool *my_pool;
00081 };
00082
00083 }
00085
00086 #if _MSC_VER && !defined(__INTEL_COMPILER)
00087
00088 #pragma warning (push)
00089 #pragma warning (disable: 4100)
00090 #endif
00091
00093
00094 template<typename T, typename P = internal::pool_base>
00095 class memory_pool_allocator {
00096 protected:
00097 typedef P pool_type;
00098 pool_type *my_pool;
00099 template<typename U, typename R>
00100 friend class memory_pool_allocator;
00101 template<typename V, typename U, typename R>
00102 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00103 template<typename V, typename U, typename R>
00104 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00105 public:
00106 typedef typename tbb::internal::allocator_type<T>::value_type value_type;
00107 typedef value_type* pointer;
00108 typedef const value_type* const_pointer;
00109 typedef value_type& reference;
00110 typedef const value_type& const_reference;
00111 typedef size_t size_type;
00112 typedef ptrdiff_t difference_type;
00113 template<typename U> struct rebind {
00114 typedef memory_pool_allocator<U, P> other;
00115 };
00116
00117 memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
00118 memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00119 template<typename U>
00120 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00121
00122 pointer address(reference x) const { return &x; }
00123 const_pointer address(const_reference x) const { return &x; }
00124
00126 pointer allocate( size_type n, const void* = 0) {
00127 return static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
00128 }
00130 void deallocate( pointer p, size_type ) {
00131 my_pool->free(p);
00132 }
00134 size_type max_size() const throw() {
00135 size_type max = static_cast<size_type>(-1) / sizeof (value_type);
00136 return (max > 0 ? max : 1);
00137 }
00139 #if __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00140 template<typename... Args>
00141 void construct(pointer p, Args&&... args)
00142 #if __TBB_CPP11_STD_FORWARD_BROKEN
00143 { ::new((void *)p) T((args)...); }
00144 #else
00145 { ::new((void *)p) T(std::forward<Args>(args)...); }
00146 #endif
00147 #else // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00148 void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); }
00149 #endif // __TBB_CPP11_VARIADIC_TEMPLATES_PRESENT && __TBB_CPP11_RVALUE_REF_PRESENT
00150
00152 void destroy( pointer p ) { p->~value_type(); }
00153
00154 };
00155
00156 #if _MSC_VER && !defined(__INTEL_COMPILER)
00157 #pragma warning (pop)
00158 #endif // warning 4100 is back
00159
00161
00162 template<typename P>
00163 class memory_pool_allocator<void, P> {
00164 public:
00165 typedef P pool_type;
00166 typedef void* pointer;
00167 typedef const void* const_pointer;
00168 typedef void value_type;
00169 template<typename U> struct rebind {
00170 typedef memory_pool_allocator<U, P> other;
00171 };
00172
00173 memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
00174 memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
00175 template<typename U>
00176 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
00177
00178 protected:
00179 pool_type *my_pool;
00180 template<typename U, typename R>
00181 friend class memory_pool_allocator;
00182 template<typename V, typename U, typename R>
00183 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00184 template<typename V, typename U, typename R>
00185 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
00186 };
00187
00188 template<typename T, typename U, typename P>
00189 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
00190
00191 template<typename T, typename U, typename P>
00192 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
00193
00194
00196 template <typename Alloc>
00197 class memory_pool : public internal::pool_base {
00198 Alloc my_alloc;
00199 static void *allocate_request(intptr_t pool_id, size_t & bytes);
00200 static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
00201
00202 public:
00204 memory_pool(const Alloc &src = Alloc());
00205
00207 ~memory_pool() { destroy(); }
00208
00209 };
00210
00211 class fixed_pool : public internal::pool_base {
00212 void *my_buffer;
00213 size_t my_size;
00214 inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
00215
00216 public:
00218 inline fixed_pool(void *buf, size_t size);
00220 ~fixed_pool() { destroy(); }
00221 };
00222
00224
00225 template <typename Alloc>
00226 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
00227 rml::MemPoolPolicy args(allocate_request, deallocate_request,
00228 sizeof(typename Alloc::value_type));
00229 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
00230 if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
00231 }
00232 template <typename Alloc>
00233 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
00234 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00235 const size_t unit_size = sizeof(typename Alloc::value_type);
00236 __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL);
00237 void *ptr;
00238 __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); }
00239 __TBB_CATCH(...) { return 0; }
00240 return ptr;
00241 }
00242 template <typename Alloc>
00243 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
00244 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
00245 const size_t unit_size = sizeof(typename Alloc::value_type);
00246 __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL);
00247 self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
00248 return 0;
00249 }
00250 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
00251 rml::MemPoolPolicy args(allocate_request, 0, size, true);
00252 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
00253 if( res!=rml::POOL_OK ) __TBB_THROW(std::bad_alloc());
00254 }
00255 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
00256 fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
00257 if( !__TBB_CompareAndSwapW(&self.my_size, 0, (bytes=self.my_size)) )
00258 return 0;
00259 return self.my_buffer;
00260 }
00261
00262 }
00263 using interface6::memory_pool_allocator;
00264 using interface6::memory_pool;
00265 using interface6::fixed_pool;
00266 }
00267
00268 #undef __TBBMALLOC_ASSERT
00269 #endif// __TBB_memory_pool_H