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