File indexing completed on 2025-10-31 08:42:32
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/container/detail/addressof.hpp> //boost::container::dtl: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_INTERPROCESS_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_INTERPROCESS_CATCH(...){
0221          this->cached_deallocation(chain);
0222          BOOST_INTERPROCESS_RETHROW
0223       } BOOST_INTERPROCESS_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::container::dtl::addressof(value));  }
0393 
0394    
0395    
0396    const_pointer address(const_reference value) const
0397    {  return const_pointer(boost::container::dtl::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