Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:37:01

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