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