Back to home page

EIC code displayed by LXR

 
 

    


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

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