Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:24

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