File indexing completed on 2025-02-21 10:15:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_memory_pool_H
0018 #define __TBB_memory_pool_H
0019
0020 #if !TBB_PREVIEW_MEMORY_POOL
0021 #error Set TBB_PREVIEW_MEMORY_POOL to include memory_pool.h
0022 #endif
0023
0024
0025 #include "scalable_allocator.h"
0026 #include <new> // std::bad_alloc
0027 #include <stdexcept> // std::runtime_error, std::invalid_argument
0028
0029 #include <string>
0030 #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
0031 #include <utility> // std::forward
0032 #endif
0033
0034 #if __TBB_EXTRA_DEBUG
0035 #define __TBBMALLOC_ASSERT ASSERT
0036 #else
0037 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
0038 #endif
0039
0040 namespace tbb {
0041 namespace interface6 {
0042
0043 namespace internal {
0044
0045
0046 class pool_base : tbb::internal::no_copy {
0047
0048
0049 public:
0050
0051 void recycle() { rml::pool_reset(my_pool); }
0052
0053
0054 void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
0055
0056
0057 void free(void* ptr) { rml::pool_free(my_pool, ptr); }
0058
0059
0060
0061 void *realloc(void* ptr, size_t size) {
0062 return rml::pool_realloc(my_pool, ptr, size);
0063 }
0064
0065 protected:
0066
0067 void destroy() { rml::pool_destroy(my_pool); }
0068
0069 rml::MemoryPool *my_pool;
0070 };
0071
0072 }
0073
0074
0075 #if _MSC_VER && !defined(__INTEL_COMPILER)
0076
0077 #pragma warning (push)
0078 #pragma warning (disable: 4100)
0079 #endif
0080
0081
0082
0083 template<typename T, typename P = internal::pool_base>
0084 class memory_pool_allocator {
0085 protected:
0086 typedef P pool_type;
0087 pool_type *my_pool;
0088 template<typename U, typename R>
0089 friend class memory_pool_allocator;
0090 template<typename V, typename U, typename R>
0091 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0092 template<typename V, typename U, typename R>
0093 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0094 public:
0095 typedef typename tbb::internal::allocator_type<T>::value_type value_type;
0096 typedef value_type* pointer;
0097 typedef const value_type* const_pointer;
0098 typedef value_type& reference;
0099 typedef const value_type& const_reference;
0100 typedef size_t size_type;
0101 typedef ptrdiff_t difference_type;
0102 template<typename U> struct rebind {
0103 typedef memory_pool_allocator<U, P> other;
0104 };
0105
0106 explicit memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
0107 memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
0108 template<typename U>
0109 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
0110
0111 pointer address(reference x) const { return &x; }
0112 const_pointer address(const_reference x) const { return &x; }
0113
0114
0115 pointer allocate( size_type n, const void* = 0) {
0116 pointer p = static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
0117 if (!p)
0118 tbb::internal::throw_exception(std::bad_alloc());
0119 return p;
0120 }
0121
0122 void deallocate( pointer p, size_type ) {
0123 my_pool->free(p);
0124 }
0125
0126 size_type max_size() const throw() {
0127 size_type max = static_cast<size_type>(-1) / sizeof (value_type);
0128 return (max > 0 ? max : 1);
0129 }
0130
0131 #if __TBB_ALLOCATOR_CONSTRUCT_VARIADIC
0132 template<typename U, typename... Args>
0133 void construct(U *p, Args&&... args)
0134 { ::new((void *)p) U(std::forward<Args>(args)...); }
0135 #else
0136 #if __TBB_CPP11_RVALUE_REF_PRESENT
0137 void construct( pointer p, value_type&& value ) {::new((void*)(p)) value_type(std::move(value));}
0138 #endif
0139 void construct( pointer p, const value_type& value ) { ::new((void*)(p)) value_type(value); }
0140 #endif
0141
0142
0143 void destroy( pointer p ) { p->~value_type(); }
0144
0145 };
0146
0147 #if _MSC_VER && !defined(__INTEL_COMPILER)
0148 #pragma warning (pop)
0149 #endif
0150
0151
0152
0153 template<typename P>
0154 class memory_pool_allocator<void, P> {
0155 public:
0156 typedef P pool_type;
0157 typedef void* pointer;
0158 typedef const void* const_pointer;
0159 typedef void value_type;
0160 template<typename U> struct rebind {
0161 typedef memory_pool_allocator<U, P> other;
0162 };
0163
0164 explicit memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
0165 memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
0166 template<typename U>
0167 memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
0168
0169 protected:
0170 pool_type *my_pool;
0171 template<typename U, typename R>
0172 friend class memory_pool_allocator;
0173 template<typename V, typename U, typename R>
0174 friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0175 template<typename V, typename U, typename R>
0176 friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0177 };
0178
0179 template<typename T, typename U, typename P>
0180 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
0181
0182 template<typename T, typename U, typename P>
0183 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
0184
0185
0186
0187 template <typename Alloc>
0188 class memory_pool : public internal::pool_base {
0189 Alloc my_alloc;
0190 static void *allocate_request(intptr_t pool_id, size_t & bytes);
0191 static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
0192
0193 public:
0194
0195 explicit memory_pool(const Alloc &src = Alloc());
0196
0197
0198 ~memory_pool() { destroy(); }
0199
0200 };
0201
0202 class fixed_pool : public internal::pool_base {
0203 void *my_buffer;
0204 size_t my_size;
0205 inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
0206
0207 public:
0208
0209 inline fixed_pool(void *buf, size_t size);
0210
0211 ~fixed_pool() { destroy(); }
0212 };
0213
0214
0215
0216 template <typename Alloc>
0217 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
0218 rml::MemPoolPolicy args(allocate_request, deallocate_request,
0219 sizeof(typename Alloc::value_type));
0220 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
0221 if (res!=rml::POOL_OK)
0222 tbb::internal::throw_exception(std::runtime_error("Can't create pool"));
0223 }
0224 template <typename Alloc>
0225 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
0226 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
0227 const size_t unit_size = sizeof(typename Alloc::value_type);
0228 __TBBMALLOC_ASSERT( 0 == bytes%unit_size, NULL);
0229 void *ptr;
0230 __TBB_TRY { ptr = self.my_alloc.allocate( bytes/unit_size ); }
0231 __TBB_CATCH(...) { return 0; }
0232 return ptr;
0233 }
0234 #if __TBB_MSVC_UNREACHABLE_CODE_IGNORED
0235
0236
0237 #pragma warning (push)
0238 #pragma warning (disable: 4702)
0239 #endif
0240 template <typename Alloc>
0241 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
0242 memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
0243 const size_t unit_size = sizeof(typename Alloc::value_type);
0244 __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, NULL);
0245 self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
0246 return 0;
0247 }
0248 #if __TBB_MSVC_UNREACHABLE_CODE_IGNORED
0249 #pragma warning (pop)
0250 #endif
0251 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
0252 if (!buf || !size)
0253
0254 tbb::internal::throw_exception(std::invalid_argument("Zero in parameter is invalid"));
0255 rml::MemPoolPolicy args(allocate_request, 0, size, true);
0256 rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
0257 if (res!=rml::POOL_OK)
0258 tbb::internal::throw_exception(std::runtime_error("Can't create pool"));
0259 }
0260 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
0261 fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
0262 __TBBMALLOC_ASSERT(0 != self.my_size, "The buffer must not be used twice.");
0263 bytes = self.my_size;
0264 self.my_size = 0;
0265 return self.my_buffer;
0266 }
0267
0268 }
0269 using interface6::memory_pool_allocator;
0270 using interface6::memory_pool;
0271 using interface6::fixed_pool;
0272 }
0273
0274 #undef __TBBMALLOC_ASSERT
0275 #endif