Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-29 07:53:51

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/interprocess for documentation.
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 //!Object function that creates the node allocator if it is not created and
0080 //!increments reference count if it is already created
0081 template<class NodePool>
0082 struct get_or_create_node_pool_func
0083 {
0084 
0085    //!This connects or constructs the unique instance of node_pool_t
0086    //!Can throw boost::interprocess::bad_alloc
0087    void operator()()
0088    {
0089       //Find or create the node_pool_t
0090       mp_node_pool =    mp_segment_manager->template find_or_construct
0091                         <NodePool>(boost::interprocess::unique_instance)(mp_segment_manager);
0092       //If valid, increment link count
0093       if(mp_node_pool != 0)
0094          mp_node_pool->inc_ref_count();
0095    }
0096 
0097    //!Constructor. Initializes function
0098    //!object parameters
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 //!Object function that decrements the reference count. If the count
0115 //!reaches to zero destroys the node allocator from memory.
0116 //!Never throws
0117 template<class NodePool>
0118 struct destroy_if_last_link_func
0119 {
0120    //!Decrements reference count and destroys the object if there is no
0121    //!more attached allocators. Never throws
0122    void operator()()
0123    {
0124       //If not the last link return
0125       if(mp_node_pool->dec_ref_count() != 0) return;
0126 
0127       //Last link, let's destroy the segment_manager
0128       mp_node_pool->get_segment_manager()->template destroy<NodePool>(boost::interprocess::unique_instance);
0129    }
0130 
0131    //!Constructor. Initializes function
0132    //!object parameters
0133    destroy_if_last_link_func(NodePool *pool)
0134       : mp_node_pool(pool)
0135    {}
0136 
0137    NodePool                           *mp_node_pool;
0138 };
0139 
0140 //!Destruction function, initializes and executes destruction function
0141 //!object. Never throws
0142 template<class NodePool>
0143 inline void destroy_node_pool_if_last_link(NodePool *pool)
0144 {
0145    //Get segment manager
0146    typename NodePool::segment_manager *mngr = pool->get_segment_manager();
0147    //Execute destruction functor atomically
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       //If don't have any cached node, we have to get a new list of free nodes from the pool
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          //If don't have any cached node, we have to get a new list of free nodes from the pool
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       //Check if cache is full
0230       if(m_cached_nodes.size() >= m_max_cached_nodes){
0231          //This only occurs if this allocator deallocate memory allocated
0232          //with other equal allocator. Since the cache is full, and more
0233          //deallocations are probably coming, we'll make some room in cache
0234          //in a single, efficient multi node deallocation.
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       //Check if cache is full
0245       if(m_cached_nodes.size() >= m_max_cached_nodes){
0246          //This only occurs if this allocator deallocate memory allocated
0247          //with other equal allocator. Since the cache is full, and more
0248          //deallocations are probably coming, we'll make some room in cache
0249          //in a single, efficient multi node deallocation.
0250          this->priv_deallocate_n_nodes(m_cached_nodes.size() - m_max_cached_nodes/2);
0251       }
0252    }
0253 
0254    //!Sets the new max cached nodes value. This can provoke deallocations
0255    //!if "newmax" is less than current cached nodes. Never throws
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    //!Frees all cached nodes.
0263    //!Never throws
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    //!Frees all cached nodes at once.
0272    //!Never throws
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    //!Frees n cached nodes at once. Never throws
0281    void priv_deallocate_n_nodes(size_type n)
0282    {
0283       //This only occurs if this allocator deallocate memory allocated
0284       //with other equal allocator. Since the cache is full, and more
0285       //deallocations are probably coming, we'll make some room in cache
0286       //in a single, efficient multi node deallocation.
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       //Deallocate all new linked list at once
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    //!Returns maximum the number of objects the previously allocated memory
0337    //!pointed by p can hold. This size only works for memory allocated with
0338    //!allocate, allocation_command and allocate_many.
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    //!Allocates many elements of size elem_size in a contiguous block
0355    //!of memory. The minimum number to be allocated is min_elements,
0356    //!the preferred and maximum number is
0357    //!preferred_elements. The number of actually allocated elements is
0358    //!will be assigned to received_size. The elements must be deallocated
0359    //!with deallocate(...)
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    //!Allocates n_elements elements, each one of size elem_sizes[i]in a
0369    //!contiguous block
0370    //!of memory. The elements must be deallocated
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    //!Allocates many elements of size elem_size in a contiguous block
0377    //!of memory. The minimum number to be allocated is min_elements,
0378    //!the preferred and maximum number is
0379    //!preferred_elements. The number of actually allocated elements is
0380    //!will be assigned to received_size. The elements must be deallocated
0381    //!with deallocate(...)
0382    void deallocate_many(multiallocation_chain &chain)
0383    {  this->derived()->get_segment_manager()->deallocate_many(chain); }
0384 
0385    //!Returns the number of elements that could be
0386    //!allocated. Never throws
0387    size_type max_size() const
0388    {  return this->derived()->get_segment_manager()->get_size()/sizeof(T);  }
0389 
0390    //!Returns address of mutable object.
0391    //!Never throws
0392    pointer address(reference value) const
0393    {  return pointer(boost::container::dtl::addressof(value));  }
0394 
0395    //!Returns address of non mutable object.
0396    //!Never throws
0397    const_pointer address(const_reference value) const
0398    {  return const_pointer(boost::container::dtl::addressof(value));  }
0399 
0400    //!Constructs an object
0401    //!Throws if T's constructor throws
0402    //!For backwards compatibility with libraries using C++03 allocators
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    //!Destroys object. Throws if object's
0408    //!destructor throws
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    //!Allocate memory for an array of count elements.
0459    //!Throws boost::interprocess::bad_alloc if there is no enough memory
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    //!Deallocate allocated memory. Never throws
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    //!Allocates just one object. Memory allocated with this function
0491    //!must be deallocated only with deallocate_one().
0492    //!Throws boost::interprocess::bad_alloc if there is no enough memory
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    //!Allocates many elements of size == 1 in a contiguous block
0501    //!of memory. The minimum number to be allocated is min_elements,
0502    //!the preferred and maximum number is
0503    //!preferred_elements. The number of actually allocated elements is
0504    //!will be assigned to received_size. Memory allocated with this function
0505    //!must be deallocated only with deallocate_one().
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    //!Deallocates memory previously allocated with allocate_one().
0514    //!You should never use deallocate_one to deallocate memory allocated
0515    //!with other functions different from allocate_one(). Never throws
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    //!Allocates many elements of size == 1 in a contiguous block
0524    //!of memory. The minimum number to be allocated is min_elements,
0525    //!the preferred and maximum number is
0526    //!preferred_elements. The number of actually allocated elements is
0527    //!will be assigned to received_size. Memory allocated with this function
0528    //!must be deallocated only with deallocate_one().
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    //!Deallocates all free blocks of the pool
0536    void deallocate_free_blocks()
0537    {  node_pool<0>::get(this->derived()->get_node_pool())->deallocate_free_blocks();  }
0538 
0539    //!Deprecated, use deallocate_free_blocks.
0540    //!Deallocates all free chunks of the pool.
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    //!Copy constructor from related cached_adaptive_pool_base. If not present, constructs
0581    //!a node pool. Increments the reference count of the associated node pool.
0582    //!Can throw boost::interprocess::bad_alloc
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    //!Returns a pointer to the node pool.
0591    //!Never throws
0592    node_pool_t* get_node_pool() const
0593    {  return m_cache.get_node_pool();   }
0594 
0595    //!Returns the segment manager.
0596    //!Never throws
0597    segment_manager* get_segment_manager()const
0598    {  return m_cache.get_segment_manager();   }
0599 
0600    //!Sets the new max cached nodes value. This can provoke deallocations
0601    //!if "newmax" is less than current cached nodes. Never throws
0602    void set_max_cached_nodes(size_type newmax)
0603    {  m_cache.set_max_cached_nodes(newmax);   }
0604 
0605    //!Returns the max cached nodes parameter.
0606    //!Never throws
0607    size_type get_max_cached_nodes() const
0608    {  return m_cache.get_max_cached_nodes();   }
0609 
0610    //!Allocate memory for an array of count elements.
0611    //!Throws boost::interprocess::bad_alloc if there is no enough memory
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    //!Deallocate allocated memory. Never throws
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    //!Allocates just one object. Memory allocated with this function
0641    //!must be deallocated only with deallocate_one().
0642    //!Throws boost::interprocess::bad_alloc if there is no enough memory
0643    pointer allocate_one()
0644    {  return pointer(static_cast<value_type*>(this->m_cache.cached_allocation()));   }
0645 
0646    //!Allocates many elements of size == 1 in a contiguous block
0647    //!of memory. The minimum number to be allocated is min_elements,
0648    //!the preferred and maximum number is
0649    //!preferred_elements. The number of actually allocated elements is
0650    //!will be assigned to received_size. Memory allocated with this function
0651    //!must be deallocated only with deallocate_one().
0652    void allocate_individual(size_type num_elements, multiallocation_chain &chain)
0653    {  this->m_cache.cached_allocation(num_elements, chain);   }
0654 
0655    //!Deallocates memory previously allocated with allocate_one().
0656    //!You should never use deallocate_one to deallocate memory allocated
0657    //!with other functions different from allocate_one(). Never throws
0658    void deallocate_one(const pointer &p)
0659    {  this->m_cache.cached_deallocation(ipcdetail::to_raw_pointer(p)); }
0660 
0661    //!Allocates many elements of size == 1 in a contiguous block
0662    //!of memory. The minimum number to be allocated is min_elements,
0663    //!the preferred and maximum number is
0664    //!preferred_elements. The number of actually allocated elements is
0665    //!will be assigned to received_size. Memory allocated with this function
0666    //!must be deallocated only with deallocate_one().
0667    void deallocate_individual(multiallocation_chain &chain)
0668    {  m_cache.cached_deallocation(chain);  }
0669 
0670    //!Deallocates all free blocks of the pool
0671    void deallocate_free_blocks()
0672    {  m_cache.get_node_pool()->deallocate_free_blocks();   }
0673 
0674    //!Swaps allocators. Does not throw. If each allocator is placed in a
0675    //!different shared memory segments, the result is undefined.
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    //!Deprecated use deallocate_free_blocks.
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   //!defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0690 };
0691 
0692 //!Equality test for same type of
0693 //!cached_allocator_impl
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 //!Inequality test for same type of
0700 //!cached_allocator_impl
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 //!Pooled shared memory allocator using adaptive pool. Includes
0708 //!a reference count but the class does not delete itself, this is
0709 //!responsibility of user classes. Node size (NodeSize) and the number of
0710 //!nodes allocated per block (NodesPerBlock) are known at compile time
0711 template<class private_node_allocator_t>
0712 class shared_pool_impl
0713    : public private_node_allocator_t
0714 {
0715  public:
0716    //!Segment manager typedef
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    //!Constructor from a segment manager. Never throws
0729    shared_pool_impl(segment_manager *segment_mngr)
0730       : private_node_allocator_t(segment_mngr)
0731    {}
0732 
0733    //!Destructor. Deallocates all allocated blocks. Never throws
0734    ~shared_pool_impl()
0735    {}
0736 
0737    //!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
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    //!Deallocates an array pointed by ptr. Never throws
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    //!Allocates n nodes.
0756    //!Can throw boost::interprocess::bad_alloc
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    //!Deallocates a linked list of nodes ending in null pointer. Never throws
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    //!Deallocates the nodes pointed by the multiallocation iterator. Never throws
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    //!Deallocates all the free blocks of memory. Never throws
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    //!Deallocates all used memory from the common pool.
0793    //!Precondition: all nodes allocated from this pool should
0794    //!already be deallocated. Otherwise, undefined behavior. Never throws
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    //!Increments internal reference count and returns new count. Never throws
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    //!Decrements internal reference count and returns new count. Never throws
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    //!Deprecated, use deallocate_free_blocks.
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    //!Deprecated, use purge_blocks.
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    //!This struct includes needed data and derives from
0842    //!the mutex type to allow EBO when using null_mutex
0843    struct header_t : mutex_type
0844    {
0845       size_type m_usecount;    //Number of attached allocators
0846 
0847       header_t()
0848       :  m_usecount(0) {}
0849    } m_header;
0850 };
0851 
0852 }  //namespace ipcdetail {
0853 }  //namespace interprocess {
0854 }  //namespace boost {
0855 
0856 #include <boost/interprocess/detail/config_end.hpp>
0857 
0858 #endif   //#ifndef BOOST_INTERPROCESS_ALLOCATOR_DETAIL_ALLOCATOR_COMMON_HPP