Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-22 10:09:04

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