memory_pool.h

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2012 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: avoid linkage with libtbb on IA-64
00032 #include <new> // std::bad_alloc
00033 #if __TBB_CPP11_RVALUE_REF_PRESENT && !__TBB_CPP11_STD_FORWARD_BROKEN
00034 #include <utility> // std::forward
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     // Pool interface is separate from standard allocator classes because it has
00051     // to maintain internal state, no copy or assignment. Move and swap are possible.
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     // Enables some low-level optimization possibilities
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 } // namespace internal
00077 
00078 #if _MSC_VER && !defined(__INTEL_COMPILER)
00079     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
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* /*hint*/ = 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; // TODO: base-class optimization
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(); } // call the callbacks first and destroy my_alloc latter
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, /*fixedPool=*/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; // all the memory was given already
00251     return self.my_buffer;
00252 }
00253 
00254 } //namespace interface6
00255 using interface6::memory_pool_allocator;
00256 using interface6::memory_pool;
00257 using interface6::fixed_pool;
00258 } //namespace tbb
00259 
00260 #undef __TBBMALLOC_ASSERT
00261 #endif// __TBB_memory_pool_H

Copyright © 2005-2012 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.