Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:46:49

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-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_PRIVATE_ADAPTIVE_POOL_HPP
0012 #define BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_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/assert.hpp>
0029 #include <boost/container/detail/addressof.hpp>
0030 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
0031 #include <boost/interprocess/containers/version_type.hpp>
0032 #include <boost/container/detail/multiallocation_chain.hpp>
0033 #include <boost/interprocess/exceptions.hpp>
0034 #include <boost/interprocess/detail/utilities.hpp>
0035 #include <boost/interprocess/detail/workaround.hpp>
0036 #include <boost/move/adl_move_swap.hpp>
0037 #include <cstddef>
0038 
0039 //!\file
0040 //!Describes private_adaptive_pool_base pooled shared memory STL compatible allocator
0041 
0042 namespace boost {
0043 namespace interprocess {
0044 
0045 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0046 
0047 namespace ipcdetail {
0048 
0049 template < unsigned int Version
0050          , class T
0051          , class SegmentManager
0052          , std::size_t NodesPerBlock
0053          , std::size_t MaxFreeBlocks
0054          , unsigned char OverheadPercent
0055          >
0056 class private_adaptive_pool_base
0057    : public node_pool_allocation_impl
0058    < private_adaptive_pool_base < Version, T, SegmentManager, NodesPerBlock
0059                                 , MaxFreeBlocks, OverheadPercent>
0060    , Version
0061    , T
0062    , SegmentManager
0063    >
0064 {
0065    public:
0066    //Segment manager
0067    typedef SegmentManager                                segment_manager;
0068    typedef typename SegmentManager::void_pointer         void_pointer;
0069 
0070    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0071    private:
0072    typedef private_adaptive_pool_base
0073       < Version, T, SegmentManager, NodesPerBlock
0074       , MaxFreeBlocks, OverheadPercent>                  self_t;
0075    typedef ipcdetail::private_adaptive_node_pool
0076       <SegmentManager
0077       , sizeof_value<T>::value
0078       , NodesPerBlock
0079       , MaxFreeBlocks
0080       , OverheadPercent
0081       > node_pool_t;
0082 
0083    BOOST_INTERPROCESS_STATIC_ASSERT((Version <=2));
0084 
0085    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0086 
0087    public:
0088    typedef typename boost::intrusive::
0089       pointer_traits<void_pointer>::template
0090          rebind_pointer<T>::type                         pointer;
0091    typedef typename boost::intrusive::
0092       pointer_traits<void_pointer>::template
0093          rebind_pointer<const T>::type                   const_pointer;
0094    typedef T                                             value_type;
0095    typedef typename ipcdetail::add_reference
0096                      <value_type>::type                  reference;
0097    typedef typename ipcdetail::add_reference
0098                      <const value_type>::type            const_reference;
0099    typedef typename segment_manager::size_type           size_type;
0100    typedef typename segment_manager::difference_type     difference_type;
0101    typedef boost::interprocess::version_type
0102       <private_adaptive_pool_base, Version>              version;
0103    typedef boost::container::dtl::transform_multiallocation_chain
0104       <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
0105 
0106    //!Obtains node_allocator from other node_allocator
0107    template<class T2>
0108    struct rebind
0109    {
0110       typedef private_adaptive_pool_base
0111          <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>   other;
0112    };
0113 
0114    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0115 
0116    template <int dummy>
0117    struct node_pool
0118    {
0119       typedef ipcdetail::private_adaptive_node_pool
0120       <SegmentManager
0121       , sizeof_value<T>::value
0122       , NodesPerBlock
0123       , MaxFreeBlocks
0124       , OverheadPercent
0125       > type;
0126 
0127       static type *get(void *p)
0128       {  return static_cast<type*>(p);  }
0129    };
0130 
0131    private:
0132    //!Not assignable from related private_adaptive_pool_base
0133    template<unsigned int Version2, class T2, class MemoryAlgorithm2, std::size_t N2, std::size_t F2, unsigned char OP2>
0134    private_adaptive_pool_base& operator=
0135       (const private_adaptive_pool_base<Version2, T2, MemoryAlgorithm2, N2, F2, OP2>&);
0136 
0137    //!Not assignable from other private_adaptive_pool_base
0138    private_adaptive_pool_base& operator=(const private_adaptive_pool_base&);
0139    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0140 
0141    public:
0142    //!Constructor from a segment manager
0143    private_adaptive_pool_base(segment_manager *segment_mngr)
0144       : m_node_pool(segment_mngr)
0145    {}
0146 
0147    //!Copy constructor from other private_adaptive_pool_base. Never throws
0148    private_adaptive_pool_base(const private_adaptive_pool_base &other)
0149       : m_node_pool(other.get_segment_manager())
0150    {}
0151 
0152    //!Copy constructor from related private_adaptive_pool_base. Never throws.
0153    template<class T2>
0154    private_adaptive_pool_base
0155       (const private_adaptive_pool_base
0156          <Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0157       : m_node_pool(other.get_segment_manager())
0158    {}
0159 
0160    //!Destructor, frees all used memory. Never throws
0161    ~private_adaptive_pool_base()
0162    {}
0163 
0164    //!Returns the segment manager. Never throws
0165    segment_manager* get_segment_manager()const
0166    {  return m_node_pool.get_segment_manager(); }
0167 
0168    //!Returns the internal node pool. Never throws
0169    node_pool_t* get_node_pool() const
0170    {  return const_cast<node_pool_t*>(&m_node_pool); }
0171 
0172    //!Swaps allocators. Does not throw. If each allocator is placed in a
0173    //!different shared memory segments, the result is undefined.
0174    friend void swap(self_t &alloc1,self_t &alloc2)
0175    {  boost::adl_move_swap(alloc1.m_node_pool, alloc2.m_node_pool);  }
0176 
0177    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0178    private:
0179    node_pool_t m_node_pool;
0180    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0181 };
0182 
0183 //!Equality test for same type of private_adaptive_pool_base
0184 template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0185 bool operator==(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
0186                 const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
0187 {  return &alloc1 == &alloc2; }
0188 
0189 //!Inequality test for same type of private_adaptive_pool_base
0190 template<unsigned int V, class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0191 bool operator!=(const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc1,
0192                 const private_adaptive_pool_base<V, T, S, NodesPerBlock, F, OP> &alloc2)
0193 {  return &alloc1 != &alloc2; }
0194 
0195 template < class T
0196          , class SegmentManager
0197          , std::size_t NodesPerBlock = 64
0198          , std::size_t MaxFreeBlocks = 2
0199          , unsigned char OverheadPercent = 5
0200          >
0201 class private_adaptive_pool_v1
0202    :  public private_adaptive_pool_base
0203          < 1
0204          , T
0205          , SegmentManager
0206          , NodesPerBlock
0207          , MaxFreeBlocks
0208          , OverheadPercent
0209          >
0210 {
0211    public:
0212    typedef ipcdetail::private_adaptive_pool_base
0213          < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0214 
0215    template<class T2>
0216    struct rebind
0217    {
0218       typedef private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
0219    };
0220 
0221    private_adaptive_pool_v1(SegmentManager *segment_mngr)
0222       : base_t(segment_mngr)
0223    {}
0224 
0225    template<class T2>
0226    private_adaptive_pool_v1
0227       (const private_adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0228       : base_t(other)
0229    {}
0230 };
0231 
0232 }  //namespace ipcdetail {
0233 
0234 #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0235 
0236 //!An STL node allocator that uses a segment manager as memory
0237 //!source. The internal pointer type will of the same type (raw, smart) as
0238 //!"typename SegmentManager::void_pointer" type. This allows
0239 //!placing the allocator in shared memory, memory mapped-files, etc...
0240 //!This allocator has its own node pool.
0241 //!
0242 //!NodesPerBlock is the minimum number of nodes of nodes allocated at once when
0243 //!the allocator needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
0244 //!that the adaptive node pool will hold. The rest of the totally free blocks will be
0245 //!deallocated with the segment manager.
0246 //!
0247 //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
0248 //!(memory usable for nodes / total memory allocated from the segment manager)
0249 template < class T
0250          , class SegmentManager
0251          , std::size_t NodesPerBlock
0252          , std::size_t MaxFreeBlocks
0253          , unsigned char OverheadPercent
0254          >
0255 class private_adaptive_pool
0256    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0257    :  public ipcdetail::private_adaptive_pool_base
0258          < 2
0259          , T
0260          , SegmentManager
0261          , NodesPerBlock
0262          , MaxFreeBlocks
0263          , OverheadPercent
0264          >
0265    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0266 {
0267 
0268    #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0269    typedef ipcdetail::private_adaptive_pool_base
0270          < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0271    public:
0272    typedef boost::interprocess::version_type<private_adaptive_pool, 2>   version;
0273 
0274    template<class T2>
0275    struct rebind
0276    {
0277       typedef private_adaptive_pool
0278          <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
0279    };
0280 
0281    private_adaptive_pool(SegmentManager *segment_mngr)
0282       : base_t(segment_mngr)
0283    {}
0284 
0285    template<class T2>
0286    private_adaptive_pool
0287       (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0288       : base_t(other)
0289    {}
0290 
0291    #else
0292    public:
0293    typedef implementation_defined::segment_manager       segment_manager;
0294    typedef segment_manager::void_pointer                 void_pointer;
0295    typedef implementation_defined::pointer               pointer;
0296    typedef implementation_defined::const_pointer         const_pointer;
0297    typedef T                                             value_type;
0298    typedef typename ipcdetail::add_reference
0299                      <value_type>::type                  reference;
0300    typedef typename ipcdetail::add_reference
0301                      <const value_type>::type            const_reference;
0302    typedef typename segment_manager::size_type           size_type;
0303    typedef typename segment_manager::difference_type     difference_type;
0304 
0305    //!Obtains private_adaptive_pool from
0306    //!private_adaptive_pool
0307    template<class T2>
0308    struct rebind
0309    {
0310       typedef private_adaptive_pool
0311          <T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0312    };
0313 
0314    private:
0315    //!Not assignable from
0316    //!related private_adaptive_pool
0317    template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
0318    private_adaptive_pool& operator=
0319       (const private_adaptive_pool<T2, SegmentManager2, N2, F2>&);
0320 
0321    //!Not assignable from
0322    //!other private_adaptive_pool
0323    private_adaptive_pool& operator=(const private_adaptive_pool&);
0324 
0325    public:
0326    //!Constructor from a segment manager. If not present, constructs a node
0327    //!pool. Increments the reference count of the associated node pool.
0328    //!Can throw boost::interprocess::bad_alloc
0329    private_adaptive_pool(segment_manager *segment_mngr);
0330 
0331    //!Copy constructor from other private_adaptive_pool. Increments the reference
0332    //!count of the associated node pool. Never throws
0333    private_adaptive_pool(const private_adaptive_pool &other);
0334 
0335    //!Copy constructor from related private_adaptive_pool. If not present, constructs
0336    //!a node pool. Increments the reference count of the associated node pool.
0337    //!Can throw boost::interprocess::bad_alloc
0338    template<class T2>
0339    private_adaptive_pool
0340       (const private_adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other);
0341 
0342    //!Destructor, removes node_pool_t from memory
0343    //!if its reference count reaches to zero. Never throws
0344    ~private_adaptive_pool();
0345 
0346    //!Returns a pointer to the node pool.
0347    //!Never throws
0348    node_pool_t* get_node_pool() const;
0349 
0350    //!Returns the segment manager.
0351    //!Never throws
0352    segment_manager* get_segment_manager()const;
0353 
0354    //!Returns the number of elements that could be allocated.
0355    //!Never throws
0356    size_type max_size() const;
0357 
0358    //!Allocate memory for an array of count elements.
0359    //!Throws boost::interprocess::bad_alloc if there is no enough memory
0360    pointer allocate(size_type count, cvoid_pointer hint = 0);
0361 
0362    //!Deallocate allocated memory.
0363    //!Never throws
0364    void deallocate(const pointer &ptr, size_type count);
0365 
0366    //!Deallocates all free blocks
0367    //!of the pool
0368    void deallocate_free_blocks();
0369 
0370    //!Swaps allocators. Does not throw. If each allocator is placed in a
0371    //!different memory segment, the result is undefined.
0372    friend void swap(self_t &alloc1, self_t &alloc2);
0373 
0374    //!Returns address of mutable object.
0375    //!Never throws
0376    pointer address(reference value) const;
0377 
0378    //!Returns address of non mutable object.
0379    //!Never throws
0380    const_pointer address(const_reference value) const;
0381 
0382    //!Copy construct an object.
0383    //!Throws if T's copy constructor throws
0384    void construct(const pointer &ptr, const_reference v);
0385 
0386    //!Destroys object. Throws if object's
0387    //!destructor throws
0388    void destroy(const pointer &ptr);
0389 
0390    //!Returns maximum the number of objects the previously allocated memory
0391    //!pointed by p can hold. This size only works for memory allocated with
0392    //!allocate, allocation_command and allocate_many.
0393    size_type size(const pointer &p) const;
0394 
0395    pointer allocation_command(boost::interprocess::allocation_type command,
0396                          size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse);
0397 
0398    //!Allocates many elements of size elem_size in a contiguous block
0399    //!of memory. The minimum number to be allocated is min_elements,
0400    //!the preferred and maximum number is
0401    //!preferred_elements. The number of actually allocated elements is
0402    //!will be assigned to received_size. The elements must be deallocated
0403    //!with deallocate(...)
0404    void allocate_many(size_type elem_size, size_type num_elements, multiallocation_chain &chain);
0405 
0406    //!Allocates n_elements elements, each one of size elem_sizes[i]in a
0407    //!contiguous block
0408    //!of memory. The elements must be deallocated
0409    void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain);
0410 
0411    //!Allocates many elements of size elem_size in a contiguous block
0412    //!of memory. The minimum number to be allocated is min_elements,
0413    //!the preferred and maximum number is
0414    //!preferred_elements. The number of actually allocated elements is
0415    //!will be assigned to received_size. The elements must be deallocated
0416    //!with deallocate(...)
0417    void deallocate_many(multiallocation_chain &chain);
0418 
0419    //!Allocates just one object. Memory allocated with this function
0420    //!must be deallocated only with deallocate_one().
0421    //!Throws boost::interprocess::bad_alloc if there is no enough memory
0422    pointer allocate_one();
0423 
0424    //!Allocates many elements of size == 1 in a contiguous block
0425    //!of memory. The minimum number to be allocated is min_elements,
0426    //!the preferred and maximum number is
0427    //!preferred_elements. The number of actually allocated elements is
0428    //!will be assigned to received_size. Memory allocated with this function
0429    //!must be deallocated only with deallocate_one().
0430    void allocate_individual(size_type num_elements, multiallocation_chain &chain);
0431 
0432    //!Deallocates memory previously allocated with allocate_one().
0433    //!You should never use deallocate_one to deallocate memory allocated
0434    //!with other functions different from allocate_one(). Never throws
0435    void deallocate_one(const pointer &p);
0436 
0437    //!Allocates many elements of size == 1 in a contiguous block
0438    //!of memory. The minimum number to be allocated is min_elements,
0439    //!the preferred and maximum number is
0440    //!preferred_elements. The number of actually allocated elements is
0441    //!will be assigned to received_size. Memory allocated with this function
0442    //!must be deallocated only with deallocate_one().
0443    void deallocate_individual(multiallocation_chain &chain);
0444    #endif
0445 };
0446 
0447 #ifdef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0448 
0449 //!Equality test for same type
0450 //!of private_adaptive_pool
0451 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0452 bool operator==(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0453                 const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
0454 
0455 //!Inequality test for same type
0456 //!of private_adaptive_pool
0457 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0458 bool operator!=(const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0459                 const private_adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
0460 
0461 #endif
0462 
0463 }  //namespace interprocess {
0464 }  //namespace boost {
0465 
0466 #include <boost/interprocess/detail/config_end.hpp>
0467 
0468 #endif   //#ifndef BOOST_INTERPROCESS_PRIVATE_ADAPTIVE_POOL_HPP
0469