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