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