1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2005-2012. 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/interprocess for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP 12 #define BOOST_INTERPROCESS_CACHED_ADAPTIVE_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/interprocess/detail/config_begin.hpp> 23 #include <boost/interprocess/detail/workaround.hpp> 24 25 #include <boost/interprocess/interprocess_fwd.hpp> 26 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp> 27 #include <boost/interprocess/allocators/detail/allocator_common.hpp> 28 #include <boost/interprocess/detail/utilities.hpp> 29 #include <boost/interprocess/detail/workaround.hpp> 30 #include <boost/interprocess/containers/version_type.hpp> 31 #include <boost/interprocess/allocators/detail/node_tools.hpp> 32 #include <cstddef> 33 34 //!\file 35 //!Describes cached_adaptive_pool pooled shared memory STL compatible allocator 36 37 namespace boost { 38 namespace interprocess { 39 40 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 41 42 namespace ipcdetail { 43 44 template < class T 45 , class SegmentManager 46 , std::size_t NodesPerBlock = 64 47 , std::size_t MaxFreeBlocks = 2 48 , unsigned char OverheadPercent = 5 49 > 50 class cached_adaptive_pool_v1 51 : public ipcdetail::cached_allocator_impl 52 < T 53 , ipcdetail::shared_adaptive_node_pool 54 < SegmentManager 55 , sizeof_value<T>::value 56 , NodesPerBlock 57 , MaxFreeBlocks 58 , OverheadPercent 59 > 60 , 1> 61 { 62 public: 63 typedef ipcdetail::cached_allocator_impl 64 < T 65 , ipcdetail::shared_adaptive_node_pool 66 < SegmentManager 67 , sizeof_value<T>::value 68 , NodesPerBlock 69 , MaxFreeBlocks 70 , OverheadPercent 71 > 72 , 1> base_t; 73 74 template<class T2> 75 struct rebind 76 { 77 typedef cached_adaptive_pool_v1 78 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; 79 }; 80 81 typedef typename base_t::size_type size_type; 82 cached_adaptive_pool_v1(SegmentManager * segment_mngr,size_type max_cached_nodes=base_t::DEFAULT_MAX_CACHED_NODES)83 cached_adaptive_pool_v1(SegmentManager *segment_mngr, 84 size_type max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) 85 : base_t(segment_mngr, max_cached_nodes) 86 {} 87 88 template<class T2> cached_adaptive_pool_v1(const cached_adaptive_pool_v1<T2,SegmentManager,NodesPerBlock,MaxFreeBlocks,OverheadPercent> & other)89 cached_adaptive_pool_v1 90 (const cached_adaptive_pool_v1 91 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other) 92 : base_t(other) 93 {} 94 }; 95 96 } //namespace ipcdetail{ 97 98 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 99 100 //!An STL node allocator that uses a segment manager as memory 101 //!source. The internal pointer type will of the same type (raw, smart) as 102 //!"typename SegmentManager::void_pointer" type. This allows 103 //!placing the allocator in shared memory, memory mapped-files, etc... 104 //! 105 //!This node allocator shares a segregated storage between all instances of 106 //!cached_adaptive_pool with equal sizeof(T) placed in the same 107 //!memory segment. But also caches some nodes privately to 108 //!avoid some synchronization overhead. 109 //! 110 //!NodesPerBlock is the minimum number of nodes of nodes allocated at once when 111 //!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks 112 //!that the adaptive node pool will hold. The rest of the totally free blocks will be 113 //!deallocated with the segment manager. 114 //! 115 //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator: 116 //!(memory usable for nodes / total memory allocated from the segment manager) 117 template < class T 118 , class SegmentManager 119 , std::size_t NodesPerBlock 120 , std::size_t MaxFreeBlocks 121 , unsigned char OverheadPercent 122 > 123 class cached_adaptive_pool 124 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 125 : public ipcdetail::cached_allocator_impl 126 < T 127 , ipcdetail::shared_adaptive_node_pool 128 < SegmentManager 129 , sizeof_value<T>::value 130 , NodesPerBlock 131 , MaxFreeBlocks 132 , OverheadPercent 133 > 134 , 2> 135 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 136 { 137 138 #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 139 public: 140 typedef ipcdetail::cached_allocator_impl 141 < T 142 , ipcdetail::shared_adaptive_node_pool 143 < SegmentManager 144 , sizeof_value<T>::value 145 , NodesPerBlock 146 , MaxFreeBlocks 147 , OverheadPercent 148 > 149 , 2> base_t; 150 151 public: 152 typedef boost::interprocess::version_type<cached_adaptive_pool, 2> version; 153 154 template<class T2> 155 struct rebind 156 { 157 typedef cached_adaptive_pool 158 <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; 159 }; 160 cached_adaptive_pool(SegmentManager * segment_mngr,std::size_t max_cached_nodes=base_t::DEFAULT_MAX_CACHED_NODES)161 cached_adaptive_pool(SegmentManager *segment_mngr, 162 std::size_t max_cached_nodes = base_t::DEFAULT_MAX_CACHED_NODES) 163 : base_t(segment_mngr, max_cached_nodes) 164 {} 165 166 template<class T2> cached_adaptive_pool(const cached_adaptive_pool<T2,SegmentManager,NodesPerBlock,MaxFreeBlocks,OverheadPercent> & other)167 cached_adaptive_pool 168 (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other) 169 : base_t(other) 170 {} 171 172 #else 173 public: 174 typedef implementation_defined::segment_manager segment_manager; 175 typedef segment_manager::void_pointer void_pointer; 176 typedef implementation_defined::pointer pointer; 177 typedef implementation_defined::const_pointer const_pointer; 178 typedef T value_type; 179 typedef typename ipcdetail::add_reference 180 <value_type>::type reference; 181 typedef typename ipcdetail::add_reference 182 <const value_type>::type const_reference; 183 typedef typename segment_manager::size_type size_type; 184 typedef typename segment_manager::difference_type difference_type; 185 186 //!Obtains cached_adaptive_pool from 187 //!cached_adaptive_pool 188 template<class T2> 189 struct rebind 190 { 191 typedef cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other; 192 }; 193 194 private: 195 //!Not assignable from 196 //!related cached_adaptive_pool 197 template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2> 198 cached_adaptive_pool& operator= 199 (const cached_adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&); 200 201 //!Not assignable from 202 //!other cached_adaptive_pool 203 cached_adaptive_pool& operator=(const cached_adaptive_pool&); 204 205 public: 206 //!Constructor from a segment manager. If not present, constructs a node 207 //!pool. Increments the reference count of the associated node pool. 208 //!Can throw boost::interprocess::bad_alloc 209 cached_adaptive_pool(segment_manager *segment_mngr); 210 211 //!Copy constructor from other cached_adaptive_pool. Increments the reference 212 //!count of the associated node pool. Never throws 213 cached_adaptive_pool(const cached_adaptive_pool &other); 214 215 //!Copy constructor from related cached_adaptive_pool. If not present, constructs 216 //!a node pool. Increments the reference count of the associated node pool. 217 //!Can throw boost::interprocess::bad_alloc 218 template<class T2> 219 cached_adaptive_pool 220 (const cached_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other); 221 222 //!Destructor, removes node_pool_t from memory 223 //!if its reference count reaches to zero. Never throws 224 ~cached_adaptive_pool(); 225 226 //!Returns a pointer to the node pool. 227 //!Never throws 228 node_pool_t* get_node_pool() const; 229 230 //!Returns the segment manager. 231 //!Never throws 232 segment_manager* get_segment_manager()const; 233 234 //!Returns the number of elements that could be allocated. 235 //!Never throws 236 size_type max_size() const; 237 238 //!Allocate memory for an array of count elements. 239 //!Throws boost::interprocess::bad_alloc if there is no enough memory 240 pointer allocate(size_type count, cvoid_pointer hint = 0); 241 242 //!Deallocate allocated memory. 243 //!Never throws 244 void deallocate(const pointer &ptr, size_type count); 245 246 //!Deallocates all free blocks 247 //!of the pool 248 void deallocate_free_blocks(); 249 250 //!Swaps allocators. Does not throw. If each allocator is placed in a 251 //!different memory segment, the result is undefined. 252 friend void swap(self_t &alloc1, self_t &alloc2); 253 254 //!Returns address of mutable object. 255 //!Never throws 256 pointer address(reference value) const; 257 258 //!Returns address of non mutable object. 259 //!Never throws 260 const_pointer address(const_reference value) const; 261 262 //!Copy construct an object. 263 //!Throws if T's copy constructor throws 264 void construct(const pointer &ptr, const_reference v); 265 266 //!Destroys object. Throws if object's 267 //!destructor throws 268 void destroy(const pointer &ptr); 269 270 //!Returns maximum the number of objects the previously allocated memory 271 //!pointed by p can hold. This size only works for memory allocated with 272 //!allocate, allocation_command and allocate_many. 273 size_type size(const pointer &p) const; 274 275 pointer allocation_command(boost::interprocess::allocation_type command, 276 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse); 277 278 //!Allocates many elements of size elem_size in a contiguous block 279 //!of memory. The minimum number to be allocated is min_elements, 280 //!the preferred and maximum number is 281 //!preferred_elements. The number of actually allocated elements is 282 //!will be assigned to received_size. The elements must be deallocated 283 //!with deallocate(...) 284 void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain); 285 286 //!Allocates n_elements elements, each one of size elem_sizes[i]in a 287 //!contiguous block 288 //!of memory. The elements must be deallocated 289 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain); 290 291 //!Allocates many elements of size elem_size in a contiguous block 292 //!of memory. The minimum number to be allocated is min_elements, 293 //!the preferred and maximum number is 294 //!preferred_elements. The number of actually allocated elements is 295 //!will be assigned to received_size. The elements must be deallocated 296 //!with deallocate(...) 297 void deallocate_many(multiallocation_chain &chain); 298 299 //!Allocates just one object. Memory allocated with this function 300 //!must be deallocated only with deallocate_one(). 301 //!Throws boost::interprocess::bad_alloc if there is no enough memory 302 pointer allocate_one(); 303 304 //!Allocates many elements of size == 1 in a contiguous block 305 //!of memory. The minimum number to be allocated is min_elements, 306 //!the preferred and maximum number is 307 //!preferred_elements. The number of actually allocated elements is 308 //!will be assigned to received_size. Memory allocated with this function 309 //!must be deallocated only with deallocate_one(). 310 multiallocation_chain allocate_individual(size_type num_elements); 311 312 //!Deallocates memory previously allocated with allocate_one(). 313 //!You should never use deallocate_one to deallocate memory allocated 314 //!with other functions different from allocate_one(). Never throws 315 void deallocate_one(const pointer &p); 316 317 //!Allocates many elements of size == 1 in a contiguous block 318 //!of memory. The minimum number to be allocated is min_elements, 319 //!the preferred and maximum number is 320 //!preferred_elements. The number of actually allocated elements is 321 //!will be assigned to received_size. Memory allocated with this function 322 //!must be deallocated only with deallocate_one(). 323 void deallocate_individual(multiallocation_chain &chain); 324 //!Sets the new max cached nodes value. This can provoke deallocations 325 //!if "newmax" is less than current cached nodes. Never throws 326 void set_max_cached_nodes(size_type newmax); 327 328 //!Returns the max cached nodes parameter. 329 //!Never throws 330 size_type get_max_cached_nodes() const; 331 #endif 332 }; 333 334 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED 335 336 //!Equality test for same type 337 //!of cached_adaptive_pool 338 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline 339 bool operator==(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, 340 const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); 341 342 //!Inequality test for same type 343 //!of cached_adaptive_pool 344 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, std::size_t OP> inline 345 bool operator!=(const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1, 346 const cached_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2); 347 348 #endif 349 350 } //namespace interprocess { 351 } //namespace boost { 352 353 354 #include <boost/interprocess/detail/config_end.hpp> 355 356 #endif //#ifndef BOOST_INTERPROCESS_CACHED_ADAPTIVE_POOL_HPP 357 358