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