Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/oneapi/tbb/memory_pool.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     Copyright (c) 2005-2022 Intel Corporation
0003 
0004     Licensed under the Apache License, Version 2.0 (the "License");
0005     you may not use this file except in compliance with the License.
0006     You may obtain a copy of the License at
0007 
0008         http://www.apache.org/licenses/LICENSE-2.0
0009 
0010     Unless required by applicable law or agreed to in writing, software
0011     distributed under the License is distributed on an "AS IS" BASIS,
0012     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013     See the License for the specific language governing permissions and
0014     limitations under the License.
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 /** @file */
0024 
0025 #include "scalable_allocator.h"
0026 
0027 #include <new> // std::bad_alloc
0028 #include <stdexcept> // std::runtime_error, std::invalid_argument
0029 #include <utility> // std::forward
0030 
0031 
0032 #if __TBB_EXTRA_DEBUG
0033 #define __TBBMALLOC_ASSERT ASSERT
0034 #else
0035 #define __TBBMALLOC_ASSERT(a,b) ((void)0)
0036 #endif
0037 
0038 namespace tbb {
0039 namespace detail {
0040 namespace d1 {
0041 
0042 //! Base of thread-safe pool allocator for variable-size requests
0043 class pool_base : no_copy {
0044     // Pool interface is separate from standard allocator classes because it has
0045     // to maintain internal state, no copy or assignment. Move and swap are possible.
0046 public:
0047     //! Reset pool to reuse its memory (free all objects at once)
0048     void recycle() { rml::pool_reset(my_pool); }
0049 
0050     //! The "malloc" analogue to allocate block of memory of size bytes
0051     void *malloc(size_t size) { return rml::pool_malloc(my_pool, size); }
0052 
0053     //! The "free" analogue to discard a previously allocated piece of memory.
0054     void free(void* ptr) { rml::pool_free(my_pool, ptr); }
0055 
0056     //! The "realloc" analogue complementing pool_malloc.
0057     // Enables some low-level optimization possibilities
0058     void *realloc(void* ptr, size_t size) {
0059         return rml::pool_realloc(my_pool, ptr, size);
0060     }
0061 
0062 protected:
0063     //! destroy pool - must be called in a child class
0064     void destroy() { rml::pool_destroy(my_pool); }
0065 
0066     rml::MemoryPool *my_pool;
0067 };
0068 
0069 #if _MSC_VER && !defined(__INTEL_COMPILER)
0070     // Workaround for erroneous "unreferenced parameter" warning in method destroy.
0071     #pragma warning (push)
0072     #pragma warning (disable: 4100)
0073 #endif
0074 
0075 //! Meets "allocator" requirements of ISO C++ Standard, Section 20.1.5
0076 /** @ingroup memory_allocation */
0077 template<typename T, typename P = pool_base>
0078 class memory_pool_allocator {
0079 protected:
0080     typedef P pool_type;
0081     pool_type *my_pool;
0082     template<typename U, typename R>
0083     friend class memory_pool_allocator;
0084     template<typename V, typename U, typename R>
0085     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0086     template<typename V, typename U, typename R>
0087     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0088 public:
0089     typedef T value_type;
0090     typedef value_type* pointer;
0091     typedef const value_type* const_pointer;
0092     typedef value_type& reference;
0093     typedef const value_type& const_reference;
0094     typedef size_t size_type;
0095     typedef ptrdiff_t difference_type;
0096     template<typename U> struct rebind {
0097         typedef memory_pool_allocator<U, P> other;
0098     };
0099 
0100     explicit memory_pool_allocator(pool_type &pool) throw() : my_pool(&pool) {}
0101     memory_pool_allocator(const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
0102     template<typename U>
0103     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
0104 
0105     pointer address(reference x) const { return &x; }
0106     const_pointer address(const_reference x) const { return &x; }
0107 
0108     //! Allocate space for n objects.
0109     pointer allocate( size_type n, const void* /*hint*/ = nullptr) {
0110         pointer p = static_cast<pointer>( my_pool->malloc( n*sizeof(value_type) ) );
0111         if (!p)
0112             throw_exception(std::bad_alloc());
0113         return p;
0114     }
0115     //! Free previously allocated block of memory.
0116     void deallocate( pointer p, size_type ) {
0117         my_pool->free(p);
0118     }
0119     //! Largest value for which method allocate might succeed.
0120     size_type max_size() const throw() {
0121         size_type max = static_cast<size_type>(-1) / sizeof (value_type);
0122         return (max > 0 ? max : 1);
0123     }
0124     //! Copy-construct value at location pointed to by p.
0125 
0126     template<typename U, typename... Args>
0127     void construct(U *p, Args&&... args)
0128         { ::new((void *)p) U(std::forward<Args>(args)...); }
0129 
0130     //! Destroy value at location pointed to by p.
0131     void destroy( pointer p ) { p->~value_type(); }
0132 
0133 };
0134 
0135 #if _MSC_VER && !defined(__INTEL_COMPILER)
0136     #pragma warning (pop)
0137 #endif // warning 4100 is back
0138 
0139 //! Analogous to std::allocator<void>, as defined in ISO C++ Standard, Section 20.4.1
0140 /** @ingroup memory_allocation */
0141 template<typename P>
0142 class memory_pool_allocator<void, P> {
0143 public:
0144     typedef P pool_type;
0145     typedef void* pointer;
0146     typedef const void* const_pointer;
0147     typedef void value_type;
0148     template<typename U> struct rebind {
0149         typedef memory_pool_allocator<U, P> other;
0150     };
0151 
0152     explicit memory_pool_allocator( pool_type &pool) throw() : my_pool(&pool) {}
0153     memory_pool_allocator( const memory_pool_allocator& src) throw() : my_pool(src.my_pool) {}
0154     template<typename U>
0155     memory_pool_allocator(const memory_pool_allocator<U,P>& src) throw() : my_pool(src.my_pool) {}
0156 
0157 protected:
0158     pool_type *my_pool;
0159     template<typename U, typename R>
0160     friend class memory_pool_allocator;
0161     template<typename V, typename U, typename R>
0162     friend bool operator==( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0163     template<typename V, typename U, typename R>
0164     friend bool operator!=( const memory_pool_allocator<V,R>& a, const memory_pool_allocator<U,R>& b);
0165 };
0166 
0167 template<typename T, typename U, typename P>
0168 inline bool operator==( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool==b.my_pool;}
0169 
0170 template<typename T, typename U, typename P>
0171 inline bool operator!=( const memory_pool_allocator<T,P>& a, const memory_pool_allocator<U,P>& b) {return a.my_pool!=b.my_pool;}
0172 
0173 //! Thread-safe growable pool allocator for variable-size requests
0174 template <typename Alloc>
0175 class memory_pool : public pool_base {
0176     Alloc my_alloc; // TODO: base-class optimization
0177     static void *allocate_request(intptr_t pool_id, size_t & bytes);
0178     static int deallocate_request(intptr_t pool_id, void*, size_t raw_bytes);
0179 
0180 public:
0181     //! construct pool with underlying allocator
0182     explicit memory_pool(const Alloc &src = Alloc());
0183 
0184     //! destroy pool
0185     ~memory_pool() { destroy(); } // call the callbacks first and destroy my_alloc latter
0186 };
0187 
0188 class fixed_pool : public pool_base {
0189     void *my_buffer;
0190     size_t my_size;
0191     inline static void *allocate_request(intptr_t pool_id, size_t & bytes);
0192 
0193 public:
0194     //! construct pool with underlying allocator
0195     inline fixed_pool(void *buf, size_t size);
0196     //! destroy pool
0197     ~fixed_pool() { destroy(); }
0198 };
0199 
0200 //////////////// Implementation ///////////////
0201 
0202 template <typename Alloc>
0203 memory_pool<Alloc>::memory_pool(const Alloc &src) : my_alloc(src) {
0204     rml::MemPoolPolicy args(allocate_request, deallocate_request,
0205                             sizeof(typename Alloc::value_type));
0206     rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
0207     if (res!=rml::POOL_OK)
0208         throw_exception(std::runtime_error("Can't create pool"));
0209 }
0210 template <typename Alloc>
0211 void *memory_pool<Alloc>::allocate_request(intptr_t pool_id, size_t & bytes) {
0212     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
0213     const size_t unit_size = sizeof(typename Alloc::value_type);
0214     __TBBMALLOC_ASSERT( 0 == bytes%unit_size, nullptr);
0215     void *ptr;
0216 #if TBB_USE_EXCEPTIONS
0217     try {
0218 #endif
0219         ptr = self.my_alloc.allocate( bytes/unit_size );
0220 #if TBB_USE_EXCEPTIONS
0221     } catch(...) {
0222         return nullptr;
0223     }
0224 #endif
0225     return ptr;
0226 }
0227 #if __TBB_MSVC_UNREACHABLE_CODE_IGNORED
0228     // Workaround for erroneous "unreachable code" warning in the template below.
0229     // Specific for VC++ 17-18 compiler
0230     #pragma warning (push)
0231     #pragma warning (disable: 4702)
0232 #endif
0233 template <typename Alloc>
0234 int memory_pool<Alloc>::deallocate_request(intptr_t pool_id, void* raw_ptr, size_t raw_bytes) {
0235     memory_pool<Alloc> &self = *reinterpret_cast<memory_pool<Alloc>*>(pool_id);
0236     const size_t unit_size = sizeof(typename Alloc::value_type);
0237     __TBBMALLOC_ASSERT( 0 == raw_bytes%unit_size, nullptr);
0238     self.my_alloc.deallocate( static_cast<typename Alloc::value_type*>(raw_ptr), raw_bytes/unit_size );
0239     return 0;
0240 }
0241 #if __TBB_MSVC_UNREACHABLE_CODE_IGNORED
0242     #pragma warning (pop)
0243 #endif
0244 inline fixed_pool::fixed_pool(void *buf, size_t size) : my_buffer(buf), my_size(size) {
0245     if (!buf || !size)
0246         // TODO: improve support for mode with exceptions disabled
0247         throw_exception(std::invalid_argument("Zero in parameter is invalid"));
0248     rml::MemPoolPolicy args(allocate_request, nullptr, size, /*fixedPool=*/true);
0249     rml::MemPoolError res = rml::pool_create_v1(intptr_t(this), &args, &my_pool);
0250     if (res!=rml::POOL_OK)
0251         throw_exception(std::runtime_error("Can't create pool"));
0252 }
0253 inline void *fixed_pool::allocate_request(intptr_t pool_id, size_t & bytes) {
0254     fixed_pool &self = *reinterpret_cast<fixed_pool*>(pool_id);
0255     __TBBMALLOC_ASSERT(0 != self.my_size, "The buffer must not be used twice.");
0256     bytes = self.my_size;
0257     self.my_size = 0; // remember that buffer has been used
0258     return self.my_buffer;
0259 }
0260 
0261 } // namespace d1
0262 } // namespace detail
0263 
0264 inline namespace v1 {
0265 using detail::d1::memory_pool_allocator;
0266 using detail::d1::memory_pool;
0267 using detail::d1::fixed_pool;
0268 } // inline namepspace v1
0269 } // namespace tbb
0270 
0271 #undef __TBBMALLOC_ASSERT
0272 #endif// __TBB_memory_pool_H