Back to home page

EIC code displayed by LXR

 
 

    


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

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