1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP 12 #define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/container/detail/config_begin.hpp> 23 #include <boost/container/detail/workaround.hpp> 24 25 #include <boost/intrusive/set.hpp> 26 #include <boost/container/detail/multiallocation_chain.hpp> 27 #include <boost/container/detail/pool_common_alloc.hpp> 28 #include <boost/container/detail/mutex.hpp> 29 #include <boost/container/detail/adaptive_node_pool_impl.hpp> 30 #include <boost/container/detail/multiallocation_chain.hpp> 31 #include <boost/container/detail/type_traits.hpp> 32 33 #include <cstddef> 34 #include <cmath> 35 #include <cassert> 36 37 38 namespace boost { 39 namespace container { 40 namespace container_detail { 41 42 template<bool AlignOnly> 43 struct select_private_adaptive_node_pool_impl 44 { 45 typedef boost::container::container_detail:: 46 private_adaptive_node_pool_impl 47 < fake_segment_manager 48 , unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only 49 | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered 50 > type; 51 }; 52 53 //!Pooled memory allocator using an smart adaptive pool. Includes 54 //!a reference count but the class does not delete itself, this is 55 //!responsibility of user classes. Node size (NodeSize) and the number of 56 //!nodes allocated per block (NodesPerBlock) are known at compile time. 57 template< std::size_t NodeSize 58 , std::size_t NodesPerBlock 59 , std::size_t MaxFreeBlocks 60 , std::size_t OverheadPercent 61 > 62 class private_adaptive_node_pool 63 : public select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type 64 { 65 typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t; 66 //Non-copyable 67 private_adaptive_node_pool(const private_adaptive_node_pool &); 68 private_adaptive_node_pool &operator=(const private_adaptive_node_pool &); 69 70 public: 71 typedef typename base_t::multiallocation_chain multiallocation_chain; 72 static const std::size_t nodes_per_block = NodesPerBlock; 73 74 //!Constructor. Never throws private_adaptive_node_pool()75 private_adaptive_node_pool() 76 : base_t(0 77 , NodeSize 78 , NodesPerBlock 79 , MaxFreeBlocks 80 , (unsigned char)OverheadPercent) 81 {} 82 }; 83 84 //!Pooled memory allocator using adaptive pool. Includes 85 //!a reference count but the class does not delete itself, this is 86 //!responsibility of user classes. Node size (NodeSize) and the number of 87 //!nodes allocated per block (NodesPerBlock) are known at compile time 88 template< std::size_t NodeSize 89 , std::size_t NodesPerBlock 90 , std::size_t MaxFreeBlocks 91 , std::size_t OverheadPercent 92 > 93 class shared_adaptive_node_pool 94 : public private_adaptive_node_pool 95 <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> 96 { 97 private: 98 typedef private_adaptive_node_pool 99 <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t; 100 public: 101 typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain; 102 103 //!Constructor. Never throws shared_adaptive_node_pool()104 shared_adaptive_node_pool() 105 : private_node_allocator_t(){} 106 107 //!Destructor. Deallocates all allocated blocks. Never throws ~shared_adaptive_node_pool()108 ~shared_adaptive_node_pool() 109 {} 110 111 //!Allocates array of count elements. Can throw std::bad_alloc allocate_node()112 void *allocate_node() 113 { 114 //----------------------- 115 scoped_lock<default_mutex> guard(mutex_); 116 //----------------------- 117 return private_node_allocator_t::allocate_node(); 118 } 119 120 //!Deallocates an array pointed by ptr. Never throws deallocate_node(void * ptr)121 void deallocate_node(void *ptr) 122 { 123 //----------------------- 124 scoped_lock<default_mutex> guard(mutex_); 125 //----------------------- 126 private_node_allocator_t::deallocate_node(ptr); 127 } 128 129 //!Allocates a singly linked list of n nodes ending in null pointer. 130 //!can throw std::bad_alloc allocate_nodes(const std::size_t n,multiallocation_chain & chain)131 void allocate_nodes(const std::size_t n, multiallocation_chain &chain) 132 { 133 //----------------------- 134 scoped_lock<default_mutex> guard(mutex_); 135 //----------------------- 136 return private_node_allocator_t::allocate_nodes(n, chain); 137 } 138 deallocate_nodes(multiallocation_chain & chain)139 void deallocate_nodes(multiallocation_chain &chain) 140 { 141 //----------------------- 142 scoped_lock<default_mutex> guard(mutex_); 143 //----------------------- 144 private_node_allocator_t::deallocate_nodes(chain); 145 } 146 147 //!Deallocates all the free blocks of memory. Never throws deallocate_free_blocks()148 void deallocate_free_blocks() 149 { 150 //----------------------- 151 scoped_lock<default_mutex> guard(mutex_); 152 //----------------------- 153 private_node_allocator_t::deallocate_free_blocks(); 154 } 155 156 private: 157 default_mutex mutex_; 158 }; 159 160 } //namespace container_detail { 161 } //namespace container { 162 } //namespace boost { 163 164 #include <boost/container/detail/config_end.hpp> 165 166 #endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP 167