// // mp::mempool // // Copyright (C) 2008 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #ifndef MP_MEMPOOL_H__ #define MP_MEMPOOL_H__ #include #include #include #include "mp/utility.h" #ifndef MP_POOL_DEFAULT_ALLOCATION_SIZE #define MP_POOL_DEFAULT_ALLOCATION_SIZE 32*1024 #endif #ifndef MP_POOL_DEFAULT_LOTS_IN_CHUNK #define MP_POOL_DEFAULT_LOTS_IN_CHUNK 4 #endif #ifndef MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK #define MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK 1024 #endif namespace mp { static const size_t POOL_DEFAULT_ALLOCATION_SIZE = MP_POOL_DEFAULT_ALLOCATION_SIZE; static const size_t POOL_DEFAULT_LOTS_IN_CHUNK = MP_POOL_DEFAULT_LOTS_IN_CHUNK; static const size_t POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK = MP_POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK; template < size_t EstimatedAllocationSize = POOL_DEFAULT_ALLOCATION_SIZE, size_t OptimalLotsInChunk = POOL_DEFAULT_LOTS_IN_CHUNK > class mempool { public: mempool(); ~mempool(); public: //! Allocate memory from the pool. /* The allocated memory have to be freed using free() function. */ inline void* malloc(size_t size); //! Free the allocated memory. inline void free(void* x); //! Template version of malloc() template inline void* malloc(); public: //! Destroy the constructed object. template inline void destroy(T* x); //! Allocate memory from the pool and construct object. template inline T* construct(); MP_ARGS_BEGIN template inline T* construct(MP_ARGS_PARAMS); MP_ARGS_END private: struct chunk_t { chunk_t* next; chunk_t* prev; size_t free; size_t lots; size_t size; }; struct data_t { chunk_t* chunk; }; private: chunk_t* m_free; chunk_t* m_used; private: void* expand_free(size_t req); void splice_to_used(chunk_t* chunk); void splice_to_free(chunk_t* chunk); private: mempool(const mempool&); }; template < typename ThreadTag = main_thread_tag, size_t EstimatedAllocationSize = POOL_DEFAULT_ALLOCATION_SIZE, size_t OptimalLotsInChunk = POOL_DEFAULT_LOTS_IN_CHUNK > class singleton_mempool { public: typedef mempool pool_type; static void* malloc(size_t size) { return pool().malloc(size); } static void free(void* x) { pool().free(x); } template static void* malloc() { return pool().malloc(); } public: template static void destroy(T* x) { return pool().destroy(x); } template static T* construct() { return pool().construct(); } MP_ARGS_BEGIN template static T* construct(MP_ARGS_PARAMS) { return pool().construct(MP_ARGS_FUNC); } MP_ARGS_END private: static pool_type& pool() { static pool_type object; return object; } }; template < typename T, typename ThreadTag = main_thread_tag, size_t OptimalObjectsInChunk = POOL_ALLOCATOR_DEFAULT_OBJECTS_IN_CHUNK > class mempool_allocator { private: typedef singleton_mempool pool; public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; template struct rebind { typedef mempool_allocator other; }; mempool_allocator() throw() {} mempool_allocator(const mempool_allocator&) throw() {} template mempool_allocator(const mempool_allocator&) throw() {} ~mempool_allocator() throw() {} pointer address(reference r) { return &r; } const_pointer address(const_reference s) { return &s; } size_type max_size() throw() { return std::numeric_limits::max() / sizeof(T); } pointer allocate(size_type num, const_pointer hint = 0) { const pointer p = static_cast( pool::malloc(sizeof(T) * num) ); if (p == 0) { throw std::bad_alloc(); } return p; } void deallocate(pointer p, size_type num) { if(p == 0) { return; } pool::free(p); } void construct(pointer p, const T& r) { new ( reinterpret_cast(p) ) T(r); } void destroy(pointer p) { p->~T(); } }; } // namespace mp template bool operator==(const mp::mempool_allocator&, const mp::mempool_allocator&) throw() { return true; } template bool operator!=(const mp::mempool_allocator&, const mp::mempool_allocator&) throw() { return false; } #include "mp/mempool_impl.h" #endif /* mp/mempool.h */