Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:38:15

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_ADAPTIVE_POOL_HPP
0012 #define BOOST_INTERPROCESS_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/detail/utilities.hpp>
0031 #include <boost/interprocess/detail/type_traits.hpp>
0032 #include <boost/interprocess/allocators/detail/adaptive_node_pool.hpp>
0033 #include <boost/interprocess/containers/version_type.hpp>
0034 #include <boost/interprocess/exceptions.hpp>
0035 #include <boost/interprocess/allocators/detail/allocator_common.hpp>
0036 #include <boost/container/detail/multiallocation_chain.hpp>
0037 #include <boost/interprocess/detail/mpl.hpp>
0038 #include <boost/move/adl_move_swap.hpp>
0039 #include <cstddef>
0040 
0041 //!\file
0042 //!Describes adaptive_pool pooled shared memory STL compatible allocator
0043 
0044 namespace boost {
0045 namespace interprocess {
0046 
0047 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0048 
0049 namespace ipcdetail{
0050 
0051 template < unsigned int Version
0052          , class T
0053          , class SegmentManager
0054          , std::size_t NodesPerBlock
0055          , std::size_t MaxFreeBlocks
0056          , unsigned char OverheadPercent
0057          >
0058 class adaptive_pool_base
0059    : public node_pool_allocation_impl
0060    < adaptive_pool_base
0061       < Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
0062    , Version
0063    , T
0064    , SegmentManager
0065    >
0066 {
0067    public:
0068    typedef typename SegmentManager::void_pointer         void_pointer;
0069    typedef SegmentManager                                segment_manager;
0070    typedef adaptive_pool_base
0071       <Version, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>   self_t;
0072 
0073    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0074 
0075    template <int dummy>
0076    struct node_pool
0077    {
0078       typedef ipcdetail::shared_adaptive_node_pool
0079       < SegmentManager, sizeof_value<T>::value, NodesPerBlock, MaxFreeBlocks, OverheadPercent> type;
0080 
0081       static type *get(void *p)
0082       {  return static_cast<type*>(p);  }
0083    };
0084    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0085 
0086    BOOST_INTERPROCESS_STATIC_ASSERT((Version <=2));
0087 
0088    public:
0089    //-------
0090    typedef typename boost::intrusive::
0091       pointer_traits<void_pointer>::template
0092          rebind_pointer<T>::type                         pointer;
0093    typedef typename boost::intrusive::
0094       pointer_traits<void_pointer>::template
0095          rebind_pointer<const T>::type                   const_pointer;
0096    typedef T                                             value_type;
0097    typedef typename ipcdetail::add_reference
0098                      <value_type>::type                  reference;
0099    typedef typename ipcdetail::add_reference
0100                      <const value_type>::type            const_reference;
0101    typedef typename segment_manager::size_type           size_type;
0102    typedef typename segment_manager::difference_type     difference_type;
0103 
0104    typedef boost::interprocess::version_type<adaptive_pool_base, Version>   version;
0105    typedef boost::container::dtl::transform_multiallocation_chain
0106       <typename SegmentManager::multiallocation_chain, T>multiallocation_chain;
0107 
0108    //!Obtains adaptive_pool_base from
0109    //!adaptive_pool_base
0110    template<class T2>
0111    struct rebind
0112    {
0113       typedef adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>       other;
0114    };
0115 
0116    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0117    private:
0118    //!Not assignable from related adaptive_pool_base
0119    template<unsigned int Version2, class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char O2>
0120    adaptive_pool_base& operator=
0121       (const adaptive_pool_base<Version2, T2, SegmentManager2, N2, F2, O2>&);
0122 
0123    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0124 
0125    public:
0126    //!Constructor from a segment manager. If not present, constructs a node
0127    //!pool. Increments the reference count of the associated node pool.
0128    //!Can throw boost::interprocess::bad_alloc
0129    adaptive_pool_base(segment_manager *segment_mngr)
0130       : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(segment_mngr)) { }
0131 
0132    //!Copy constructor from other adaptive_pool_base. Increments the reference
0133    //!count of the associated node pool. Never throws
0134    adaptive_pool_base(const adaptive_pool_base &other)
0135       : mp_node_pool(other.get_node_pool())
0136    {
0137       node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count();
0138    }
0139 
0140    //!Assignment from other adaptive_pool_base
0141    adaptive_pool_base& operator=(const adaptive_pool_base &other)
0142    {
0143       adaptive_pool_base c(other);
0144       boost::adl_move_swap(*this, c);
0145       return *this;
0146    }
0147 
0148    //!Copy constructor from related adaptive_pool_base. If not present, constructs
0149    //!a node pool. Increments the reference count of the associated node pool.
0150    //!Can throw boost::interprocess::bad_alloc
0151    template<class T2>
0152    adaptive_pool_base
0153       (const adaptive_pool_base<Version, T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0154       : mp_node_pool(ipcdetail::get_or_create_node_pool<typename node_pool<0>::type>(other.get_segment_manager())) { }
0155 
0156    //!Destructor, removes node_pool_t from memory
0157    //!if its reference count reaches to zero. Never throws
0158    ~adaptive_pool_base()
0159    {  ipcdetail::destroy_node_pool_if_last_link(node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool)));   }
0160 
0161    //!Returns a pointer to the node pool.
0162    //!Never throws
0163    void* get_node_pool() const
0164    {  return ipcdetail::to_raw_pointer(mp_node_pool);   }
0165 
0166    //!Returns the segment manager.
0167    //!Never throws
0168    segment_manager* get_segment_manager()const
0169    {  return node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->get_segment_manager();  }
0170 
0171    //!Swaps allocators. Does not throw. If each allocator is placed in a
0172    //!different memory segment, the result is undefined.
0173    friend void swap(self_t &alloc1, self_t &alloc2)
0174    {  boost::adl_move_swap(alloc1.mp_node_pool, alloc2.mp_node_pool);  }
0175 
0176    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0177    private:
0178    void_pointer   mp_node_pool;
0179    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0180 };
0181 
0182 //!Equality test for same type
0183 //!of adaptive_pool_base
0184 template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
0185 bool operator==(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
0186                 const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
0187    {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
0188 
0189 //!Inequality test for same type
0190 //!of adaptive_pool_base
0191 template<unsigned int V, class T, class S, std::size_t NPC, std::size_t F, unsigned char OP> inline
0192 bool operator!=(const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc1,
0193                 const adaptive_pool_base<V, T, S, NPC, F, OP> &alloc2)
0194    {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
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 adaptive_pool_v1
0203    :  public adaptive_pool_base
0204          < 1
0205          , T
0206          , SegmentManager
0207          , NodesPerBlock
0208          , MaxFreeBlocks
0209          , OverheadPercent
0210          >
0211 {
0212    public:
0213    typedef ipcdetail::adaptive_pool_base
0214          < 1, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0215 
0216    template<class T2>
0217    struct rebind
0218    {
0219       typedef adaptive_pool_v1<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
0220    };
0221 
0222    adaptive_pool_v1(SegmentManager *segment_mngr)
0223       : base_t(segment_mngr)
0224    {}
0225 
0226    template<class T2>
0227    adaptive_pool_v1
0228       (const 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 //!
0242 //!This node allocator shares a segregated storage between all instances
0243 //!of adaptive_pool with equal sizeof(T) placed in the same segment
0244 //!group. NodesPerBlock is the number of nodes allocated at once when the allocator
0245 //!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
0246 //!that the adaptive node pool will hold. The rest of the totally free blocks will be
0247 //!deallocated with the segment manager.
0248 //!
0249 //!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
0250 //!(memory usable for nodes / total memory allocated from the segment manager)
0251 template < class T
0252          , class SegmentManager
0253          , std::size_t NodesPerBlock
0254          , std::size_t MaxFreeBlocks
0255          , unsigned char OverheadPercent
0256          >
0257 class adaptive_pool
0258    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0259    :  public ipcdetail::adaptive_pool_base
0260          < 2
0261          , T
0262          , SegmentManager
0263          , NodesPerBlock
0264          , MaxFreeBlocks
0265          , OverheadPercent
0266          >
0267    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0268 {
0269 
0270    #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
0271    typedef ipcdetail::adaptive_pool_base
0272          < 2, T, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> base_t;
0273    public:
0274    typedef boost::interprocess::version_type<adaptive_pool, 2>   version;
0275 
0276    template<class T2>
0277    struct rebind
0278    {
0279       typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent>  other;
0280    };
0281 
0282    adaptive_pool(SegmentManager *segment_mngr)
0283       : base_t(segment_mngr)
0284    {}
0285 
0286    template<class T2>
0287    adaptive_pool
0288       (const adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> &other)
0289       : base_t(other)
0290    {}
0291 
0292    #else //BOOST_INTERPROCESS_DOXYGEN_INVOKED
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 adaptive_pool from
0307    //!adaptive_pool
0308    template<class T2>
0309    struct rebind
0310    {
0311       typedef adaptive_pool<T2, SegmentManager, NodesPerBlock, MaxFreeBlocks, OverheadPercent> other;
0312    };
0313 
0314    private:
0315    //!Not assignable from
0316    //!related adaptive_pool
0317    template<class T2, class SegmentManager2, std::size_t N2, std::size_t F2, unsigned char OP2>
0318    adaptive_pool& operator=
0319       (const adaptive_pool<T2, SegmentManager2, N2, F2, OP2>&);
0320 
0321    //!Not assignable from
0322    //!other adaptive_pool
0323    //adaptive_pool& operator=(const 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    adaptive_pool(segment_manager *segment_mngr);
0330 
0331    //!Copy constructor from other adaptive_pool. Increments the reference
0332    //!count of the associated node pool. Never throws
0333    adaptive_pool(const adaptive_pool &other);
0334 
0335    //!Copy constructor from related 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    adaptive_pool
0340       (const 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    ~adaptive_pool();
0345 
0346    //!Returns a pointer to the node pool.
0347    //!Never throws
0348    void* 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 adaptive_pool
0451 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0452 bool operator==(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0453                 const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc2);
0454 
0455 //!Inequality test for same type
0456 //!of adaptive_pool
0457 template<class T, class S, std::size_t NodesPerBlock, std::size_t F, unsigned char OP> inline
0458 bool operator!=(const adaptive_pool<T, S, NodesPerBlock, F, OP> &alloc1,
0459                 const 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_ADAPTIVE_POOL_HPP
0469