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 dtl { 41 42 //!Pooled memory allocator using an smart adaptive pool. Includes 43 //!a reference count but the class does not delete itself, this is 44 //!responsibility of user classes. Node size (NodeSize) and the number of 45 //!nodes allocated per block (NodesPerBlock) are known at compile time. 46 template< std::size_t NodeSize 47 , std::size_t NodesPerBlock 48 , std::size_t MaxFreeBlocks 49 , std::size_t OverheadPercent 50 > 51 class private_adaptive_node_pool 52 : public private_adaptive_node_pool_impl_ct 53 < fake_segment_manager 54 , MaxFreeBlocks 55 , NodeSize 56 , NodesPerBlock 57 , OverheadPercent 58 , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only 59 | ::boost::container::adaptive_pool_flag::size_ordered 60 | ::boost::container::adaptive_pool_flag::address_ordered 61 > 62 { 63 typedef private_adaptive_node_pool_impl_ct 64 < fake_segment_manager 65 , MaxFreeBlocks 66 , NodeSize 67 , NodesPerBlock 68 , OverheadPercent 69 , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only 70 | ::boost::container::adaptive_pool_flag::size_ordered 71 | ::boost::container::adaptive_pool_flag::address_ordered 72 > base_t; 73 74 //Non-copyable 75 private_adaptive_node_pool(const private_adaptive_node_pool &); 76 private_adaptive_node_pool &operator=(const private_adaptive_node_pool &); 77 78 public: 79 static const std::size_t nodes_per_block = NodesPerBlock; 80 81 //!Constructor. Never throws private_adaptive_node_pool()82 private_adaptive_node_pool() 83 : base_t(0) 84 {} 85 }; 86 87 //!Pooled memory allocator using adaptive pool. Includes 88 //!a reference count but the class does not delete itself, this is 89 //!responsibility of user classes. Node size (NodeSize) and the number of 90 //!nodes allocated per block (NodesPerBlock) are known at compile time 91 template< std::size_t NodeSize 92 , std::size_t NodesPerBlock 93 , std::size_t MaxFreeBlocks 94 , std::size_t OverheadPercent 95 > 96 class shared_adaptive_node_pool 97 : public private_adaptive_node_pool 98 <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> 99 { 100 private: 101 typedef private_adaptive_node_pool 102 <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t; 103 public: 104 typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain; 105 106 //!Constructor. Never throws shared_adaptive_node_pool()107 shared_adaptive_node_pool() 108 : private_node_allocator_t(){} 109 110 //!Destructor. Deallocates all allocated blocks. Never throws ~shared_adaptive_node_pool()111 ~shared_adaptive_node_pool() 112 {} 113 114 //!Allocates array of count elements. Can throw std::bad_alloc allocate_node()115 void *allocate_node() 116 { 117 //----------------------- 118 scoped_lock<default_mutex> guard(mutex_); 119 //----------------------- 120 return private_node_allocator_t::allocate_node(); 121 } 122 123 //!Deallocates an array pointed by ptr. Never throws deallocate_node(void * ptr)124 void deallocate_node(void *ptr) 125 { 126 //----------------------- 127 scoped_lock<default_mutex> guard(mutex_); 128 //----------------------- 129 private_node_allocator_t::deallocate_node(ptr); 130 } 131 132 //!Allocates a singly linked list of n nodes ending in null pointer. 133 //!can throw std::bad_alloc allocate_nodes(const std::size_t n,multiallocation_chain & chain)134 void allocate_nodes(const std::size_t n, multiallocation_chain &chain) 135 { 136 //----------------------- 137 scoped_lock<default_mutex> guard(mutex_); 138 //----------------------- 139 return private_node_allocator_t::allocate_nodes(n, chain); 140 } 141 deallocate_nodes(multiallocation_chain & chain)142 void deallocate_nodes(multiallocation_chain &chain) 143 { 144 //----------------------- 145 scoped_lock<default_mutex> guard(mutex_); 146 //----------------------- 147 private_node_allocator_t::deallocate_nodes(chain); 148 } 149 150 //!Deallocates all the free blocks of memory. Never throws deallocate_free_blocks()151 void deallocate_free_blocks() 152 { 153 //----------------------- 154 scoped_lock<default_mutex> guard(mutex_); 155 //----------------------- 156 private_node_allocator_t::deallocate_free_blocks(); 157 } 158 159 private: 160 default_mutex mutex_; 161 }; 162 163 } //namespace dtl { 164 } //namespace container { 165 } //namespace boost { 166 167 #include <boost/container/detail/config_end.hpp> 168 169 #endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP 170