File indexing completed on 2026-04-29 07:53:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
0012 #define BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 0018 ">#
0019 #if defined(BOOST_HAS_PRAGMA_ONCE)
0020 # pragma once
0021 #endif
0022
0023 #include <boost/interprocess/detail/config_begin.hpp>
0024 #include <boost/interprocess/detail/workaround.hpp>
0025
0026 #include <boost/intrusive/pointer_traits.hpp>
0027
0028 #include <boost/interprocess/interprocess_fwd.hpp>
0029 #include <boost/interprocess/detail/utilities.hpp> //to_raw_pointer
0030 #include <boost/container/detail/addressof.hpp> //boost::container::dtl:addressof
0031 #include <boost/assert.hpp> //BOOST_ASSERT
0032 #include <boost/interprocess/exceptions.hpp> //bad_alloc
0033 #include <boost/interprocess/sync/scoped_lock.hpp> //scoped_lock
0034 #include <boost/interprocess/containers/allocation_type.hpp> //boost::interprocess::allocation_type
0035 #include <boost/container/detail/multiallocation_chain.hpp>
0036 #include <boost/interprocess/mem_algo/detail/mem_algo_common.hpp>
0037 #include <boost/interprocess/detail/segment_manager_helper.hpp>
0038 #include <boost/move/utility_core.hpp>
0039 #include <boost/interprocess/detail/type_traits.hpp>
0040 #include <boost/interprocess/detail/utilities.hpp>
0041 #include <boost/container/detail/placement_new.hpp>
0042 #include <boost/move/adl_move_swap.hpp>
0043
0044 namespace boost {
0045 namespace interprocess {
0046
0047 template <class T>
0048 struct sizeof_value
0049 {
0050 static const std::size_t value = sizeof(T);
0051 };
0052
0053 template <>
0054 struct sizeof_value<void>
0055 {
0056 static const std::size_t value = sizeof(void*);
0057 };
0058
0059 template <>
0060 struct sizeof_value<const void>
0061 {
0062 static const std::size_t value = sizeof(void*);
0063 };
0064
0065 template <>
0066 struct sizeof_value<volatile void>
0067 {
0068 static const std::size_t value = sizeof(void*);
0069 };
0070
0071 template <>
0072 struct sizeof_value<const volatile void>
0073 {
0074 static const std::size_t value = sizeof(void*);
0075 };
0076
0077 namespace ipcdetail {
0078
0079
0080
0081 template<class NodePool>
0082 struct get_or_create_node_pool_func
0083 {
0084
0085
0086
0087 void operator()()
0088 {
0089
0090 mp_node_pool = mp_segment_manager->template find_or_construct
0091 <NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
0092
0093 if(mp_node_pool != 0)
0094 mp_node_pool->inc_ref_count();
0095 }
0096
0097
0098
0099 get_or_create_node_pool_func(typename NodePool::segment_manager *mngr)
0100 : mp_segment_manager(mngr){}
0101
0102 NodePool *mp_node_pool;
0103 typename NodePool::segment_manager *mp_segment_manager;
0104 };
0105
0106 template<class NodePool>
0107 inline NodePool *get_or_create_node_pool(typename NodePool::segment_manager *mgnr)
0108 {
0109 ipcdetail::get_or_create_node_pool_func<NodePool> func(mgnr);
0110 mgnr->atomic_func(func);
0111 return func.mp_node_pool;
0112 }
0113
0114
0115
0116
0117 template<class NodePool>
0118 struct destroy_if_last_link_func
0119 {
0120
0121
0122 void operator()()
0123 {
0124
0125 if(mp_node_pool->dec_ref_count() != 0) return;
0126
0127
0128 mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
0129 }
0130
0131
0132
0133 destroy_if_last_link_func(NodePool *pool)
0134 : mp_node_pool(pool)
0135 {}
0136
0137 NodePool *mp_node_pool;
0138 };
0139
0140
0141
0142 template<class NodePool>
0143 inline void destroy_node_pool_if_last_link(NodePool *pool)
0144 {
0145
0146 typename NodePool::segment_manager *mngr = pool->get_segment_manager();
0147
0148 destroy_if_last_link_func<NodePool>func(pool);
0149 mngr->atomic_func(func);
0150 }
0151
0152 template<class NodePool>
0153 class cache_impl
0154 {
0155 typedef typename NodePool::segment_manager::
0156 void_pointer void_pointer;
0157 typedef typename boost::intrusive::
0158 pointer_traits<void_pointer>::template
0159 rebind_pointer<NodePool>::type node_pool_ptr;
0160 typedef typename NodePool::multiallocation_chain multiallocation_chain;
0161 typedef typename NodePool::segment_manager::size_type size_type;
0162 node_pool_ptr mp_node_pool;
0163 multiallocation_chain m_cached_nodes;
0164 size_type m_max_cached_nodes;
0165
0166 public:
0167 typedef typename NodePool::segment_manager segment_manager;
0168
0169 cache_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
0170 : mp_node_pool(get_or_create_node_pool<NodePool>(segment_mngr))
0171 , m_max_cached_nodes(max_cached_nodes)
0172 {}
0173
0174 cache_impl(const cache_impl &other)
0175 : mp_node_pool(other.get_node_pool())
0176 , m_max_cached_nodes(other.get_max_cached_nodes())
0177 {
0178 mp_node_pool->inc_ref_count();
0179 }
0180
0181 ~cache_impl()
0182 {
0183 this->deallocate_all_cached_nodes();
0184 ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool));
0185 }
0186
0187 NodePool *get_node_pool() const
0188 { return ipcdetail::to_raw_pointer(mp_node_pool); }
0189
0190 segment_manager *get_segment_manager() const
0191 { return mp_node_pool->get_segment_manager(); }
0192
0193 size_type get_max_cached_nodes() const
0194 { return m_max_cached_nodes; }
0195
0196 void *cached_allocation()
0197 {
0198
0199 if(m_cached_nodes.empty()){
0200 mp_node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes);
0201 }
0202 void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
0203 return ret;
0204 }
0205
0206 void cached_allocation(size_type n, multiallocation_chain &chain)
0207 {
0208 size_type count = n, allocated(0);
0209 BOOST_INTERPROCESS_TRY{
0210
0211 while(!m_cached_nodes.empty() && count--){
0212 void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front());
0213 chain.push_back(ret);
0214 ++allocated;
0215 }
0216
0217 if(allocated != n){
0218 mp_node_pool->allocate_nodes(n - allocated, chain);
0219 }
0220 }
0221 BOOST_INTERPROCESS_CATCH(...){
0222 this->cached_deallocation(chain);
0223 BOOST_INTERPROCESS_RETHROW
0224 } BOOST_INTERPROCESS_CATCH_END
0225 }
0226
0227 void cached_deallocation(void *ptr)
0228 {
0229
0230 if(m_cached_nodes.size() >= m_max_cached_nodes){
0231
0232
0233
0234
0235 this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
0236 }
0237 m_cached_nodes.push_front(ptr);
0238 }
0239
0240 void cached_deallocation(multiallocation_chain &chain)
0241 {
0242 m_cached_nodes.splice_after(m_cached_nodes.before_begin(), chain);
0243
0244
0245 if(m_cached_nodes.size() >= m_max_cached_nodes){
0246
0247
0248
0249
0250 this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
0251 }
0252 }
0253
0254
0255
0256 void set_max_cached_nodes(size_type newmax)
0257 {
0258 m_max_cached_nodes = newmax;
0259 this->priv_deallocate_remaining_nodes();
0260 }
0261
0262
0263
0264 void deallocate_all_cached_nodes()
0265 {
0266 if(m_cached_nodes.empty()) return;
0267 mp_node_pool->deallocate_nodes(m_cached_nodes);
0268 }
0269
0270 private:
0271
0272
0273 void priv_deallocate_remaining_nodes()
0274 {
0275 if(m_cached_nodes.size() > m_max_cached_nodes){
0276 priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes);
0277 }
0278 }
0279
0280
0281 void priv_deallocate_n_nodes(size_type n)
0282 {
0283
0284
0285
0286
0287 size_type count(n);
0288 typename multiallocation_chain::iterator it(m_cached_nodes.before_begin());
0289 while(count--){
0290 ++it;
0291 }
0292 multiallocation_chain chain;
0293 chain.splice_after(chain.before_begin(), m_cached_nodes, m_cached_nodes.before_begin(), it, n);
0294
0295 mp_node_pool->deallocate_nodes(chain);
0296 }
0297
0298 public:
0299 void swap(cache_impl &other)
0300 {
0301 ::boost::adl_move_swap(mp_node_pool, other.mp_node_pool);
0302 ::boost::adl_move_swap(m_cached_nodes, other.m_cached_nodes);
0303 ::boost::adl_move_swap(m_max_cached_nodes, other.m_max_cached_nodes);
0304 }
0305 };
0306
0307 template<class Derived, class T, class SegmentManager>
0308 class array_allocation_impl
0309 {
0310 const Derived *derived() const
0311 { return static_cast<const Derived*>(this); }
0312 Derived *derived()
0313 { return static_cast<Derived*>(this); }
0314
0315 typedef typename SegmentManager::void_pointer void_pointer;
0316
0317 public:
0318 typedef typename boost::intrusive::
0319 pointer_traits<void_pointer>::template
0320 rebind_pointer<T>::type pointer;
0321 typedef typename boost::intrusive::
0322 pointer_traits<void_pointer>::template
0323 rebind_pointer<const T>::type const_pointer;
0324 typedef T value_type;
0325 typedef typename ipcdetail::add_reference
0326 <value_type>::type reference;
0327 typedef typename ipcdetail::add_reference
0328 <const value_type>::type const_reference;
0329 typedef typename SegmentManager::size_type size_type;
0330 typedef typename SegmentManager::difference_type difference_type;
0331 typedef boost::container::dtl::transform_multiallocation_chain
0332 <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
0333
0334
0335 public:
0336
0337
0338
0339 size_type size(const pointer &p) const
0340 {
0341 return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T);
0342 }
0343
0344 pointer allocation_command(boost::interprocess::allocation_type command,
0345 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
0346 {
0347 value_type *reuse_raw = ipcdetail::to_raw_pointer(reuse);
0348 pointer const p = this->derived()->get_segment_manager()->allocation_command
0349 (command, limit_size, prefer_in_recvd_out_size, reuse_raw);
0350 reuse = reuse_raw;
0351 return p;
0352 }
0353
0354
0355
0356
0357
0358
0359
0360 void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain)
0361 {
0362 if(size_overflows<sizeof(T)>(elem_size)){
0363 throw bad_alloc();
0364 }
0365 this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements, chain);
0366 }
0367
0368
0369
0370
0371 void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
0372 {
0373 this->derived()->get_segment_manager()->allocate_many(elem_sizes, n_elements, sizeof(T), chain);
0374 }
0375
0376
0377
0378
0379
0380
0381
0382 void deallocate_many(multiallocation_chain &chain)
0383 { this->derived()->get_segment_manager()->deallocate_many(chain); }
0384
0385
0386
0387 size_type max_size() const
0388 { return this->derived()->get_segment_manager()->get_size()/sizeof(T); }
0389
0390
0391
0392 pointer address(reference value) const
0393 { return pointer(boost::container::dtl::addressof(value)); }
0394
0395
0396
0397 const_pointer address(const_reference value) const
0398 { return const_pointer(boost::container::dtl::addressof(value)); }
0399
0400
0401
0402
0403 template<class P>
0404 void construct(const pointer &ptr, BOOST_FWD_REF(P) p)
0405 { ::new((void*)ipcdetail::to_raw_pointer(ptr), boost_container_new_t()) value_type(::boost::forward<P>(p)); }
0406
0407
0408
0409 void destroy(const pointer &ptr)
0410 { BOOST_ASSERT(ptr != 0); (*ptr).~value_type(); }
0411 };
0412
0413
0414 template<class Derived, unsigned int Version, class T, class SegmentManager>
0415 class node_pool_allocation_impl
0416 : public array_allocation_impl
0417 < Derived
0418 , T
0419 , SegmentManager>
0420 {
0421 const Derived *derived() const
0422 { return static_cast<const Derived*>(this); }
0423 Derived *derived()
0424 { return static_cast<Derived*>(this); }
0425
0426 typedef typename SegmentManager::void_pointer void_pointer;
0427 typedef typename boost::intrusive::
0428 pointer_traits<void_pointer>::template
0429 rebind_pointer<const void>::type cvoid_pointer;
0430
0431 public:
0432 typedef typename boost::intrusive::
0433 pointer_traits<void_pointer>::template
0434 rebind_pointer<T>::type pointer;
0435 typedef typename boost::intrusive::
0436 pointer_traits<void_pointer>::template
0437 rebind_pointer<const T>::type const_pointer;
0438 typedef T value_type;
0439 typedef typename ipcdetail::add_reference
0440 <value_type>::type reference;
0441 typedef typename ipcdetail::add_reference
0442 <const value_type>::type const_reference;
0443 typedef typename SegmentManager::size_type size_type;
0444 typedef typename SegmentManager::difference_type difference_type;
0445 typedef boost::container::dtl::transform_multiallocation_chain
0446 <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
0447
0448
0449 template <int Dummy>
0450 struct node_pool
0451 {
0452 typedef typename Derived::template node_pool<0>::type type;
0453 static type *get(void *p)
0454 { return static_cast<type*>(p); }
0455 };
0456
0457 public:
0458
0459
0460 pointer allocate(size_type count, cvoid_pointer hint = 0)
0461 {
0462 (void)hint;
0463 typedef typename node_pool<0>::type node_pool_t;
0464 node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
0465 if(size_overflows<sizeof(T)>(count)){
0466 throw bad_alloc();
0467 }
0468 else if(Version == 1 && count == 1){
0469 return pointer(static_cast<value_type*>
0470 (pool->allocate_node()));
0471 }
0472 else{
0473 return pointer(static_cast<value_type*>
0474 (pool->get_segment_manager()->allocate(count*sizeof(T))));
0475 }
0476 }
0477
0478
0479 void deallocate(const pointer &ptr, size_type count)
0480 {
0481 (void)count;
0482 typedef typename node_pool<0>::type node_pool_t;
0483 node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
0484 if(Version == 1 && count == 1)
0485 pool->deallocate_node(ipcdetail::to_raw_pointer(ptr));
0486 else
0487 pool->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
0488 }
0489
0490
0491
0492
0493 pointer allocate_one()
0494 {
0495 typedef typename node_pool<0>::type node_pool_t;
0496 node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
0497 return pointer(static_cast<value_type*>(pool->allocate_node()));
0498 }
0499
0500
0501
0502
0503
0504
0505
0506 void allocate_individual(size_type num_elements, multiallocation_chain &chain)
0507 {
0508 typedef typename node_pool<0>::type node_pool_t;
0509 node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
0510 pool->allocate_nodes(num_elements, chain);
0511 }
0512
0513
0514
0515
0516 void deallocate_one(const pointer &p)
0517 {
0518 typedef typename node_pool<0>::type node_pool_t;
0519 node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool());
0520 pool->deallocate_node(ipcdetail::to_raw_pointer(p));
0521 }
0522
0523
0524
0525
0526
0527
0528
0529 void deallocate_individual(multiallocation_chain &chain)
0530 {
0531 node_pool<0>::get(this->derived()->get_node_pool())->deallocate_nodes
0532 (chain);
0533 }
0534
0535
0536 void deallocate_free_blocks()
0537 { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); }
0538
0539
0540
0541 void deallocate_free_chunks()
0542 { node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks(); }
0543 };
0544
0545 template<class T, class NodePool, unsigned int Version>
0546 class cached_allocator_impl
0547 : public array_allocation_impl
0548 <cached_allocator_impl<T, NodePool, Version>, T, typename NodePool::segment_manager>
0549 {
0550 cached_allocator_impl & operator=(const cached_allocator_impl& other);
0551 typedef array_allocation_impl
0552 < cached_allocator_impl
0553 <T, NodePool, Version>
0554 , T
0555 , typename NodePool::segment_manager> base_t;
0556
0557 public:
0558 typedef NodePool node_pool_t;
0559 typedef typename NodePool::segment_manager segment_manager;
0560 typedef typename segment_manager::void_pointer void_pointer;
0561 typedef typename boost::intrusive::
0562 pointer_traits<void_pointer>::template
0563 rebind_pointer<const void>::type cvoid_pointer;
0564 typedef typename base_t::pointer pointer;
0565 typedef typename base_t::size_type size_type;
0566 typedef typename base_t::multiallocation_chain multiallocation_chain;
0567 typedef typename base_t::value_type value_type;
0568
0569 public:
0570 static const std::size_t DEFAULT_MAX_CACHED_NODES = 64;
0571
0572 cached_allocator_impl(segment_manager *segment_mngr, size_type max_cached_nodes)
0573 : m_cache(segment_mngr, max_cached_nodes)
0574 {}
0575
0576 cached_allocator_impl(const cached_allocator_impl &other)
0577 : m_cache(other.m_cache)
0578 {}
0579
0580
0581
0582
0583 template<class T2, class NodePool2>
0584 cached_allocator_impl
0585 (const cached_allocator_impl
0586 <T2, NodePool2, Version> &other)
0587 : m_cache(other.get_segment_manager(), other.get_max_cached_nodes())
0588 {}
0589
0590
0591
0592 node_pool_t* get_node_pool() const
0593 { return m_cache.get_node_pool(); }
0594
0595
0596
0597 segment_manager* get_segment_manager()const
0598 { return m_cache.get_segment_manager(); }
0599
0600
0601
0602 void set_max_cached_nodes(size_type newmax)
0603 { m_cache.set_max_cached_nodes(newmax); }
0604
0605
0606
0607 size_type get_max_cached_nodes() const
0608 { return m_cache.get_max_cached_nodes(); }
0609
0610
0611
0612 pointer allocate(size_type count, cvoid_pointer hint = 0)
0613 {
0614 (void)hint;
0615 void * ret;
0616 if(size_overflows<sizeof(T)>(count)){
0617 throw bad_alloc();
0618 }
0619 else if(Version == 1 && count == 1){
0620 ret = m_cache.cached_allocation();
0621 }
0622 else{
0623 ret = this->get_segment_manager()->allocate(count*sizeof(T));
0624 }
0625 return pointer(static_cast<T*>(ret));
0626 }
0627
0628
0629 void deallocate(const pointer &ptr, size_type count)
0630 {
0631 (void)count;
0632 if(Version == 1 && count == 1){
0633 m_cache.cached_deallocation(ipcdetail::to_raw_pointer(ptr));
0634 }
0635 else{
0636 this->get_segment_manager()->deallocate((void*)ipcdetail::to_raw_pointer(ptr));
0637 }
0638 }
0639
0640
0641
0642
0643 pointer allocate_one()
0644 { return pointer(static_cast<value_type*>(this->m_cache.cached_allocation())); }
0645
0646
0647
0648
0649
0650
0651
0652 void allocate_individual(size_type num_elements, multiallocation_chain &chain)
0653 { this->m_cache.cached_allocation(num_elements, chain); }
0654
0655
0656
0657
0658 void deallocate_one(const pointer &p)
0659 { this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); }
0660
0661
0662
0663
0664
0665
0666
0667 void deallocate_individual(multiallocation_chain &chain)
0668 { m_cache.cached_deallocation(chain); }
0669
0670
0671 void deallocate_free_blocks()
0672 { m_cache.get_node_pool()->deallocate_free_blocks(); }
0673
0674
0675
0676 friend void swap(cached_allocator_impl &alloc1, cached_allocator_impl &alloc2)
0677 { ::boost::adl_move_swap(alloc1.m_cache, alloc2.m_cache); }
0678
0679 void deallocate_cache()
0680 { m_cache.deallocate_all_cached_nodes(); }
0681
0682
0683 void deallocate_free_chunks()
0684 { m_cache.get_node_pool()->deallocate_free_blocks(); }
0685
0686 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0687 private:
0688 cache_impl<node_pool_t> m_cache;
0689 #endif
0690 };
0691
0692
0693
0694 template<class T, class N, unsigned int V> inline
0695 bool operator==(const cached_allocator_impl<T, N, V> &alloc1,
0696 const cached_allocator_impl<T, N, V> &alloc2)
0697 { return alloc1.get_node_pool() == alloc2.get_node_pool(); }
0698
0699
0700
0701 template<class T, class N, unsigned int V> inline
0702 bool operator!=(const cached_allocator_impl<T, N, V> &alloc1,
0703 const cached_allocator_impl<T, N, V> &alloc2)
0704 { return alloc1.get_node_pool() != alloc2.get_node_pool(); }
0705
0706
0707
0708
0709
0710
0711 template<class private_node_allocator_t>
0712 class shared_pool_impl
0713 : public private_node_allocator_t
0714 {
0715 public:
0716
0717 typedef typename private_node_allocator_t::
0718 segment_manager segment_manager;
0719 typedef typename private_node_allocator_t::
0720 multiallocation_chain multiallocation_chain;
0721 typedef typename private_node_allocator_t::
0722 size_type size_type;
0723
0724 private:
0725 typedef typename segment_manager::mutex_family::mutex_type mutex_type;
0726
0727 public:
0728
0729 shared_pool_impl(segment_manager *segment_mngr)
0730 : private_node_allocator_t(segment_mngr)
0731 {}
0732
0733
0734 ~shared_pool_impl()
0735 {}
0736
0737
0738 void *allocate_node()
0739 {
0740
0741 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0742
0743 return private_node_allocator_t::allocate_node();
0744 }
0745
0746
0747 void deallocate_node(void *ptr)
0748 {
0749
0750 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0751
0752 private_node_allocator_t::deallocate_node(ptr);
0753 }
0754
0755
0756
0757 void allocate_nodes(const size_type n, multiallocation_chain &chain)
0758 {
0759
0760 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0761
0762 private_node_allocator_t::allocate_nodes(n, chain);
0763 }
0764
0765
0766 void deallocate_nodes(multiallocation_chain &nodes, size_type num)
0767 {
0768
0769 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0770
0771 private_node_allocator_t::deallocate_nodes(nodes, num);
0772 }
0773
0774
0775 void deallocate_nodes(multiallocation_chain &chain)
0776 {
0777
0778 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0779
0780 private_node_allocator_t::deallocate_nodes(chain);
0781 }
0782
0783
0784 void deallocate_free_blocks()
0785 {
0786
0787 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0788
0789 private_node_allocator_t::deallocate_free_blocks();
0790 }
0791
0792
0793
0794
0795 void purge_blocks()
0796 {
0797
0798 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0799
0800 private_node_allocator_t::purge_blocks();
0801 }
0802
0803
0804 size_type inc_ref_count()
0805 {
0806
0807 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0808
0809 return ++m_header.m_usecount;
0810 }
0811
0812
0813 size_type dec_ref_count()
0814 {
0815
0816 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0817
0818 BOOST_ASSERT(m_header.m_usecount > 0);
0819 return --m_header.m_usecount;
0820 }
0821
0822
0823 void deallocate_free_chunks()
0824 {
0825
0826 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0827
0828 private_node_allocator_t::deallocate_free_blocks();
0829 }
0830
0831
0832 void purge_chunks()
0833 {
0834
0835 boost::interprocess::scoped_lock<mutex_type> guard(m_header);
0836
0837 private_node_allocator_t::purge_blocks();
0838 }
0839
0840 private:
0841
0842
0843 struct header_t : mutex_type
0844 {
0845 size_type m_usecount;
0846
0847 header_t()
0848 : m_usecount(0) {}
0849 } m_header;
0850 };
0851
0852 }
0853 }
0854 }
0855
0856 #include <boost/interprocess/detail/config_end.hpp>
0857
0858 #endif