File indexing completed on 2025-02-22 10:09:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
0012 #define BOOST_INTERPROCESS_ADAPTIVE_POOL_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024
0025 #include <boost/intrusive/pointer_traits.hpp>
0026
0027 #include <boost/interprocess/interprocess_fwd.hpp>
0028 #include <boost/assert.hpp>
0029 #include <boost/static_assert.hpp>
0030 #include <boost/utility/addressof.hpp>
0031 #include <boost/interprocess/detail/utilities.hpp>
0032 #include <boost/interprocess/detail/type_traits.hpp>
0033 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
0034 #include <boost/interprocess/containers/version_type.hpp>
0035 #include <boost/interprocess/exceptions.hpp>
0036 #include <boost/interprocess/allocators/detail/allocator_common.hpp>
0037 #include <boost/container/detail/multiallocation_chain.hpp>
0038 #include <boost/interprocess/detail/mpl.hpp>
0039 #include <boost/move/adl_move_swap.hpp>
0040 #include <cstddef>
0041
0042
0043
0044
0045 namespace boost {
0046 namespace interprocess {
0047
0048 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0049
0050 namespace ipcdetail{
0051
0052 template < unsigned int Version
0053 , class T
0054 , class SegmentManager
0055 , std::size_t NodesPerBlock
0056 , std::size_t MaxFreeBlocks
0057 , unsigned char OverheadPercent
0058 >
0059 class adaptive_pool_base
0060 : public node_pool_allocation_impl
0061 < adaptive_pool_base
0062 < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
0063 , Version
0064 , T
0065 , SegmentManager
0066 >
0067 {
0068 public:
0069 typedef typename SegmentManager::void_pointer void_pointer;
0070 typedef SegmentManager segment_manager;
0071 typedef adaptive_pool_base
0072 <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> self_t;
0073
0074 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0075
0076 template <int dummy>
0077 struct node_pool
0078 {
0079 typedef ipcdetail::shared_adaptive_node_pool
0080 < SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
0081
0082 static type *get(void *p)
0083 { return static_cast<type*>(p); }
0084 };
0085 #endif
0086
0087 BOOST_STATIC_ASSERT((Version <=2));
0088
0089 public:
0090
0091 typedef typename boost::intrusive::
0092 pointer_traits<void_pointer>::template
0093 rebind_pointer<T>::type pointer;
0094 typedef typename boost::intrusive::
0095 pointer_traits<void_pointer>::template
0096 rebind_pointer<const T>::type const_pointer;
0097 typedef T value_type;
0098 typedef typename ipcdetail::add_reference
0099 <value_type>::type reference;
0100 typedef typename ipcdetail::add_reference
0101 <const value_type>::type const_reference;
0102 typedef typename segment_manager::size_type size_type;
0103 typedef typename segment_manager::difference_type difference_type;
0104
0105 typedef boost::interprocess::version_type<adaptive_pool_base, Version> version;
0106 typedef boost::container::dtl::transform_multiallocation_chain
0107 <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
0108
0109
0110
0111 template<class T2>
0112 struct rebind
0113 {
0114 typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0115 };
0116
0117 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0118 private:
0119
0120 template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
0121 adaptive_pool_base& operator=
0122 (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
0123
0124 #endif
0125
0126 public:
0127
0128
0129
0130 adaptive_pool_base(segment_manager *segment_mngr)
0131 : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
0132
0133
0134
0135 adaptive_pool_base(const adaptive_pool_base &other)
0136 : mp_node_pool(other.get_node_pool())
0137 {
0138 node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count();
0139 }
0140
0141
0142 adaptive_pool_base& operator=(const adaptive_pool_base &other)
0143 {
0144 adaptive_pool_base c(other);
0145 boost::adl_move_swap(*this, c);
0146 return *this;
0147 }
0148
0149
0150
0151
0152 template<class T2>
0153 adaptive_pool_base
0154 (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0155 : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
0156
0157
0158
0159 ~adaptive_pool_base()
0160 { ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))); }
0161
0162
0163
0164 void* get_node_pool() const
0165 { return ipcdetail::to_raw_pointer(mp_node_pool); }
0166
0167
0168
0169 segment_manager* get_segment_manager()const
0170 { return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager(); }
0171
0172
0173
0174 friend void swap(self_t &alloc1, self_t &alloc2)
0175 { boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool); }
0176
0177 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0178 private:
0179 void_pointer mp_node_pool;
0180 #endif
0181 };
0182
0183
0184
0185 template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
0186 bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
0187 const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
0188 { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
0189
0190
0191
0192 template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
0193 bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
0194 const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
0195 { return alloc1.get_node_pool() != alloc2.get_node_pool(); }
0196
0197 template < class T
0198 , class SegmentManager
0199 , std::size_t NodesPerBlock = 64
0200 , std::size_t MaxFreeBlocks = 2
0201 , unsigned char OverheadPercent = 5
0202 >
0203 class adaptive_pool_v1
0204 : public adaptive_pool_base
0205 < 1
0206 , T
0207 , SegmentManager
0208 , NodesPerBlock
0209 , MaxFreeBlocks
0210 , OverheadPercent
0211 >
0212 {
0213 public:
0214 typedef ipcdetail::adaptive_pool_base
0215 < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0216
0217 template<class T2>
0218 struct rebind
0219 {
0220 typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0221 };
0222
0223 adaptive_pool_v1(SegmentManager *segment_mngr)
0224 : base_t(segment_mngr)
0225 {}
0226
0227 template<class T2>
0228 adaptive_pool_v1
0229 (const adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0230 : base_t(other)
0231 {}
0232 };
0233
0234 }
0235
0236 #endif
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 template < class T
0253 , class SegmentManager
0254 , std::size_t NodesPerBlock
0255 , std::size_t MaxFreeBlocks
0256 , unsigned char OverheadPercent
0257 >
0258 class adaptive_pool
0259 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0260 : public ipcdetail::adaptive_pool_base
0261 < 2
0262 , T
0263 , SegmentManager
0264 , NodesPerBlock
0265 , MaxFreeBlocks
0266 , OverheadPercent
0267 >
0268 #endif
0269 {
0270
0271 #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0272 typedef ipcdetail::adaptive_pool_base
0273 < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0274 public:
0275 typedef boost::interprocess::version_type<adaptive_pool, 2> version;
0276
0277 template<class T2>
0278 struct rebind
0279 {
0280 typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0281 };
0282
0283 adaptive_pool(SegmentManager *segment_mngr)
0284 : base_t(segment_mngr)
0285 {}
0286
0287 template<class T2>
0288 adaptive_pool
0289 (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0290 : base_t(other)
0291 {}
0292
0293 #else
0294 public:
0295 typedef implementation_defined::segment_manager segment_manager;
0296 typedef segment_manager::void_pointer void_pointer;
0297 typedef implementation_defined::pointer pointer;
0298 typedef implementation_defined::const_pointer const_pointer;
0299 typedef T value_type;
0300 typedef typename ipcdetail::add_reference
0301 <value_type>::type reference;
0302 typedef typename ipcdetail::add_reference
0303 <const value_type>::type const_reference;
0304 typedef typename segment_manager::size_type size_type;
0305 typedef typename segment_manager::difference_type difference_type;
0306
0307
0308
0309 template<class T2>
0310 struct rebind
0311 {
0312 typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0313 };
0314
0315 private:
0316
0317
0318 template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
0319 adaptive_pool& operator=
0320 (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
0321
0322
0323
0324
0325
0326 public:
0327
0328
0329
0330 adaptive_pool(segment_manager *segment_mngr);
0331
0332
0333
0334 adaptive_pool(const adaptive_pool &other);
0335
0336
0337
0338
0339 template<class T2>
0340 adaptive_pool
0341 (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
0342
0343
0344
0345 ~adaptive_pool();
0346
0347
0348
0349 void* get_node_pool() const;
0350
0351
0352
0353 segment_manager* get_segment_manager()const;
0354
0355
0356
0357 size_type max_size() const;
0358
0359
0360
0361 pointer allocate(size_type count, cvoid_pointer hint = 0);
0362
0363
0364
0365 void deallocate(const pointer &ptr, size_type count);
0366
0367
0368
0369 void deallocate_free_blocks();
0370
0371
0372
0373 friend void swap(self_t &alloc1, self_t &alloc2);
0374
0375
0376
0377 pointer address(reference value) const;
0378
0379
0380
0381 const_pointer address(const_reference value) const;
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394 size_type size(const pointer &p) const;
0395
0396 pointer allocation_command(boost::interprocess::allocation_type command,
0397 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse);
0398
0399
0400
0401
0402
0403
0404
0405 void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
0406
0407
0408
0409
0410 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
0411
0412
0413
0414
0415
0416
0417
0418 void deallocate_many(multiallocation_chain &chain);
0419
0420
0421
0422
0423 pointer allocate_one();
0424
0425
0426
0427
0428
0429
0430
0431 void allocate_individual(size_type num_elements, multiallocation_chain &chain);
0432
0433
0434
0435
0436 void deallocate_one(const pointer &p);
0437
0438
0439
0440
0441
0442
0443
0444 void deallocate_individual(multiallocation_chain &chain);
0445 #endif
0446 };
0447
0448 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0449
0450
0451
0452 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0453 bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0454 const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
0455
0456
0457
0458 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0459 bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0460 const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
0461
0462 #endif
0463
0464 }
0465 }
0466
0467 #include <boost/interprocess/detail/config_end.hpp>
0468
0469 #endif
0470