Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:14

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2007-2013. 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/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_CONTAINER_ALLOCATOR_HPP
0012 #define BOOST_CONTAINER_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/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 #include <boost/container/container_fwd.hpp>
0025 #include <boost/container/detail/version_type.hpp>
0026 #include <boost/container/throw_exception.hpp>
0027 #include <boost/container/detail/dlmalloc.hpp>
0028 #include <boost/container/detail/multiallocation_chain.hpp>
0029 #include <boost/static_assert.hpp>
0030 
0031 #include <boost/move/detail/force_ptr.hpp>
0032 
0033 #include <cstddef>
0034 #include <cassert>
0035 
0036 //!\file
0037 
0038 namespace boost {
0039 namespace container {
0040 
0041 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0042 
0043 template<unsigned Version, unsigned int AllocationDisableMask>
0044 class allocator<void, Version, AllocationDisableMask>
0045 {
0046    typedef allocator<void, Version, AllocationDisableMask>   self_t;
0047    public:
0048    typedef void                                 value_type;
0049    typedef void *                               pointer;
0050    typedef const void*                          const_pointer;
0051    typedef int &                                reference;
0052    typedef const int &                          const_reference;
0053    typedef std::size_t                          size_type;
0054    typedef std::ptrdiff_t                       difference_type;
0055    typedef boost::container::dtl::
0056       version_type<self_t, Version>             version;
0057 
0058    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0059    typedef boost::container::dtl::
0060          basic_multiallocation_chain<void*>        multiallocation_chain;
0061    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0062 
0063    //!Obtains an allocator that allocates
0064    //!objects of type T2
0065    template<class T2>
0066    struct rebind
0067    {
0068       typedef allocator< T2
0069                        #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0070                        , Version, AllocationDisableMask
0071                        #endif
0072                        > other;
0073    };
0074 
0075    //!Default constructor
0076    //!Never throws
0077    allocator()
0078    {}
0079 
0080    //!Constructor from other allocator.
0081    //!Never throws
0082    allocator(const allocator &)
0083    {}
0084 
0085    //!Constructor from related allocator.
0086    //!Never throws
0087    template<class T2>
0088       allocator(const allocator<T2, Version, AllocationDisableMask> &)
0089    {}
0090 };
0091 
0092 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0093 
0094 //! This class is an extended STL-compatible that offers advanced allocation mechanism
0095 //!(in-place expansion, shrinking, burst-allocation...)
0096 //!
0097 //! This allocator is a wrapper around a modified DLmalloc.
0098 //! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
0099 //! the allocator offers advanced expand in place and burst allocation capabilities.
0100 //!
0101 //! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
0102 //! of allocation types the user wants to disable.
0103 template< class T
0104         , unsigned Version BOOST_CONTAINER_DOCONLY(=2)
0105         , unsigned int AllocationDisableMask BOOST_CONTAINER_DOCONLY(=0)>
0106 class allocator
0107 {
0108    typedef unsigned int allocation_type;
0109    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0110    private:
0111 
0112    //Self type
0113    typedef allocator<T, Version, AllocationDisableMask>   self_t;
0114 
0115    //Not assignable from related allocator
0116    template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
0117    allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
0118 
0119    static const unsigned int ForbiddenMask =
0120       BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
0121 
0122    //The mask can't disable all the allocation types
0123    BOOST_STATIC_ASSERT((  (AllocationDisableMask & ForbiddenMask) != ForbiddenMask  ));
0124 
0125    //The mask is only valid for version 2 allocators
0126    BOOST_STATIC_ASSERT((  Version != 1 || (AllocationDisableMask == 0)  ));
0127 
0128    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0129 
0130    public:
0131    typedef T                                    value_type;
0132    typedef T *                                  pointer;
0133    typedef const T *                            const_pointer;
0134    typedef T &                                  reference;
0135    typedef const T &                            const_reference;
0136    typedef std::size_t                          size_type;
0137    typedef std::ptrdiff_t                       difference_type;
0138 
0139    typedef boost::container::dtl::
0140       version_type<self_t, Version>                version;
0141 
0142    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0143    typedef boost::container::dtl::
0144          basic_multiallocation_chain<void*>        void_multiallocation_chain;
0145 
0146    typedef boost::container::dtl::
0147       transform_multiallocation_chain
0148          <void_multiallocation_chain, T>           multiallocation_chain;
0149    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0150 
0151    //!Obtains an allocator that allocates
0152    //!objects of type T2
0153    template<class T2>
0154    struct rebind
0155    {
0156       typedef allocator<T2, Version, AllocationDisableMask> other;
0157    };
0158 
0159    //!Default constructor
0160    //!Never throws
0161    allocator() BOOST_NOEXCEPT_OR_NOTHROW
0162    {}
0163 
0164    //!Constructor from other allocator.
0165    //!Never throws
0166    allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0167    {}
0168 
0169    //!Constructor from related allocator.
0170    //!Never throws
0171    template<class T2>
0172    allocator(const allocator<T2
0173             #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0174             , Version, AllocationDisableMask
0175             #endif
0176             > &) BOOST_NOEXCEPT_OR_NOTHROW
0177    {}
0178 
0179    //!Allocates memory for an array of count elements.
0180    //!Throws bad_alloc if there is no enough memory
0181    //!If Version is 2, this allocated memory can only be deallocated
0182    //!with deallocate() or (for Version == 2) deallocate_many()
0183    BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocate(size_type count, const void * hint= 0)
0184    {
0185       (void)hint;
0186       if(count > size_type(-1)/(2u*sizeof(T)))
0187          boost::container::throw_bad_alloc();
0188       void *ret = dlmalloc_malloc(count*sizeof(T));
0189       if(!ret)
0190          boost::container::throw_bad_alloc();
0191       return static_cast<pointer>(ret);
0192    }
0193 
0194    //!Deallocates previously allocated memory.
0195    //!Never throws
0196    BOOST_CONTAINER_FORCEINLINE void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
0197    {  dlmalloc_free(ptr);  }
0198 
0199    //!Returns the maximum number of elements that could be allocated.
0200    //!Never throws
0201    BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
0202    {  return size_type(-1)/(2u*sizeof(T));   }
0203 
0204    //!Swaps two allocators, does nothing
0205    //!because this allocator is stateless
0206    BOOST_CONTAINER_FORCEINLINE friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW
0207    {}
0208 
0209    //!An allocator always compares to true, as memory allocated with one
0210    //!instance can be deallocated by another instance
0211    BOOST_CONTAINER_ATTRIBUTE_NODISCARD
0212       friend bool operator==(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0213    {  return true;   }
0214 
0215    //!An allocator always compares to false, as memory allocated with one
0216    //!instance can be deallocated by another instance
0217    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
0218       friend bool operator!=(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
0219    {  return false;   }
0220 
0221    //!An advanced function that offers in-place expansion shrink to fit and new allocation
0222    //!capabilities. Memory allocated with this function can only be deallocated with deallocate()
0223    //!or deallocate_many().
0224    //!This function is available only with Version == 2
0225    BOOST_CONTAINER_ATTRIBUTE_NODISCARD pointer allocation_command(allocation_type command,
0226                          size_type limit_size,
0227                          size_type &prefer_in_recvd_out_size,
0228                          pointer &reuse)
0229    {
0230       BOOST_STATIC_ASSERT(( Version > 1 ));
0231       const allocation_type mask(AllocationDisableMask);
0232       command &= ~mask;
0233       pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
0234       if(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
0235          boost::container::throw_bad_alloc();
0236       return ret;
0237    }
0238 
0239    //!Returns maximum the number of objects the previously allocated memory
0240    //!pointed by p can hold.
0241    //!Memory must not have been allocated with
0242    //!allocate_one or allocate_individual.
0243    //!This function is available only with Version == 2
0244    BOOST_CONTAINER_ATTRIBUTE_NODISCARD size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
0245    {
0246       BOOST_STATIC_ASSERT(( Version > 1 ));
0247       return dlmalloc_size(p);
0248    }
0249 
0250    //!Allocates just one object. Memory allocated with this function
0251    //!must be deallocated only with deallocate_one().
0252    //!Throws bad_alloc if there is no enough memory
0253    //!This function is available only with Version == 2
0254    BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE pointer allocate_one()
0255    {
0256       BOOST_STATIC_ASSERT(( Version > 1 ));
0257       return this->allocate(1);
0258    }
0259 
0260    //!Allocates many elements of size == 1.
0261    //!Elements must be individually deallocated with deallocate_one()
0262    //!This function is available only with Version == 2
0263    BOOST_CONTAINER_FORCEINLINE void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
0264    {
0265       BOOST_STATIC_ASSERT(( Version > 1 ));
0266       this->allocate_many(1, num_elements, chain);
0267    }
0268 
0269    //!Deallocates memory previously allocated with allocate_one().
0270    //!You should never use deallocate_one to deallocate memory allocated
0271    //!with other functions different from allocate_one() or allocate_individual.
0272    //Never throws
0273    void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW
0274    {
0275       BOOST_STATIC_ASSERT(( Version > 1 ));
0276       return this->deallocate(p, 1);
0277    }
0278 
0279    //!Deallocates memory allocated with allocate_one() or allocate_individual().
0280    //!This function is available only with Version == 2
0281    BOOST_CONTAINER_FORCEINLINE
0282       void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
0283    {
0284       BOOST_STATIC_ASSERT(( Version > 1 ));
0285       return this->deallocate_many(chain);
0286    }
0287 
0288    //!Allocates many elements of size elem_size.
0289    //!Elements must be individually deallocated with deallocate()
0290    //!This function is available only with Version == 2
0291    void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
0292    {
0293       BOOST_STATIC_ASSERT(( Version > 1 ));
0294       dlmalloc_memchain ch;
0295       BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
0296       if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
0297          boost::container::throw_bad_alloc();
0298       }
0299       chain.incorporate_after(chain.before_begin()
0300                              ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
0301                              ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
0302                              ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
0303 /*
0304       if(!dlmalloc_multialloc_nodes( n_elements, elem_size*sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
0305                                    , move_detail::force_ptr<dlmalloc_memchain *>(&chain))){
0306          boost::container::throw_bad_alloc();
0307       }*/
0308    }
0309 
0310    //!Allocates n_elements elements, each one of size elem_sizes[i]
0311    //!Elements must be individually deallocated with deallocate()
0312    //!This function is available only with Version == 2
0313    void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
0314    {
0315       BOOST_STATIC_ASSERT(( Version > 1 ));
0316       dlmalloc_memchain ch;
0317       BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
0318       if(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
0319          boost::container::throw_bad_alloc();
0320       }
0321       chain.incorporate_after(chain.before_begin()
0322                              ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
0323                              ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
0324                              ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
0325       /*
0326       if(!dlmalloc_multialloc_arrays( n_elements, elem_sizes, sizeof(T), BOOST_CONTAINER_DL_MULTIALLOC_DEFAULT_CONTIGUOUS
0327                                     , move_detail::force_ptr<dlmalloc_memchain *>(&chain))){
0328          boost::container::throw_bad_alloc();
0329       }*/
0330    }
0331 
0332    //!Deallocates several elements allocated by
0333    //!allocate_many(), allocate(), or allocation_command().
0334    //!This function is available only with Version == 2
0335    void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
0336    {
0337       BOOST_STATIC_ASSERT(( Version > 1 ));
0338       dlmalloc_memchain ch;
0339       void *beg(&*chain.begin()), *last(&*chain.last());
0340       size_t size(chain.size());
0341       BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
0342       dlmalloc_multidealloc(&ch);
0343       //dlmalloc_multidealloc(move_detail::force_ptr<dlmalloc_memchain *>(&chain));
0344    }
0345 
0346    private:
0347 
0348    pointer priv_allocation_command
0349       (allocation_type command,    std::size_t limit_size
0350       ,size_type &prefer_in_recvd_out_size
0351       ,pointer &reuse_ptr)
0352    {
0353       std::size_t const preferred_size = prefer_in_recvd_out_size;
0354       dlmalloc_command_ret_t ret = {0 , 0};
0355       if((limit_size > this->max_size()) || (preferred_size > this->max_size())){
0356          return pointer();
0357       }
0358       std::size_t l_size = limit_size*sizeof(T);
0359       std::size_t p_size = preferred_size*sizeof(T);
0360       std::size_t r_size;
0361       {
0362          void* reuse_ptr_void = reuse_ptr;
0363          ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
0364          reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0;
0365       }
0366       prefer_in_recvd_out_size = r_size/sizeof(T);
0367       return (pointer)ret.first;
0368    }
0369 };
0370 
0371 }  //namespace container {
0372 }  //namespace boost {
0373 
0374 #include <boost/container/detail/config_end.hpp>
0375 
0376 #endif   //BOOST_CONTAINER_ALLOCATOR_HPP
0377