163 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| // (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost
 | |
| // Software License, Version 1.0. (See accompanying file
 | |
| // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| // See http://www.boost.org/libs/container for documentation.
 | |
| //
 | |
| //////////////////////////////////////////////////////////////////////////////
 | |
| 
 | |
| #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
 | |
| #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
 | |
| 
 | |
| #ifndef BOOST_CONFIG_HPP
 | |
| #  include <boost/config.hpp>
 | |
| #endif
 | |
| 
 | |
| #if defined(BOOST_HAS_PRAGMA_ONCE)
 | |
| #  pragma once
 | |
| #endif
 | |
| 
 | |
| #include <boost/container/detail/config_begin.hpp>
 | |
| #include <boost/container/detail/workaround.hpp>
 | |
| 
 | |
| #include <boost/container/allocator_traits.hpp>             //allocator_traits
 | |
| #include <boost/container/throw_exception.hpp>
 | |
| #include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
 | |
| #include <boost/container/detail/version_type.hpp>          //version_type
 | |
| #include <boost/container/detail/allocation_type.hpp>       //allocation_type
 | |
| #include <boost/container/detail/mpl.hpp>                   //integral_constant
 | |
| #include <boost/intrusive/pointer_traits.hpp>               //pointer_traits
 | |
| #include <boost/core/no_exceptions_support.hpp>             //BOOST_TRY
 | |
| 
 | |
| namespace boost {
 | |
| namespace container {
 | |
| namespace container_detail {
 | |
| 
 | |
| template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
 | |
| struct allocator_version_traits
 | |
| {
 | |
|    typedef ::boost::container::container_detail::integral_constant
 | |
|       <unsigned, Version> alloc_version;
 | |
| 
 | |
|    typedef typename Allocator::multiallocation_chain multiallocation_chain;
 | |
| 
 | |
|    typedef typename boost::container::allocator_traits<Allocator>::pointer    pointer;
 | |
|    typedef typename boost::container::allocator_traits<Allocator>::size_type  size_type;
 | |
| 
 | |
|    //Node allocation interface
 | |
|    static pointer allocate_one(Allocator &a)
 | |
|    {  return a.allocate_one();   }
 | |
| 
 | |
|    static void deallocate_one(Allocator &a, const pointer &p)
 | |
|    {  a.deallocate_one(p);   }
 | |
| 
 | |
|    static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
 | |
|    {  return a.allocate_individual(n, m);   }
 | |
| 
 | |
|    static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
 | |
|    {  a.deallocate_individual(holder);   }
 | |
| 
 | |
|    static pointer allocation_command(Allocator &a, allocation_type command,
 | |
|                          size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
 | |
|    {  return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);  }
 | |
| };
 | |
| 
 | |
| template<class Allocator>
 | |
| struct allocator_version_traits<Allocator, 1>
 | |
| {
 | |
|    typedef ::boost::container::container_detail::integral_constant
 | |
|       <unsigned, 1> alloc_version;
 | |
| 
 | |
|    typedef typename boost::container::allocator_traits<Allocator>::pointer    pointer;
 | |
|    typedef typename boost::container::allocator_traits<Allocator>::size_type  size_type;
 | |
|    typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
 | |
| 
 | |
|    typedef typename boost::intrusive::pointer_traits<pointer>::
 | |
|          template rebind_pointer<void>::type                void_ptr;
 | |
|    typedef container_detail::basic_multiallocation_chain
 | |
|       <void_ptr>                                            multialloc_cached_counted;
 | |
|    typedef boost::container::container_detail::
 | |
|       transform_multiallocation_chain
 | |
|          < multialloc_cached_counted, value_type>           multiallocation_chain;
 | |
| 
 | |
|    //Node allocation interface
 | |
|    static pointer allocate_one(Allocator &a)
 | |
|    {  return a.allocate(1);   }
 | |
| 
 | |
|    static void deallocate_one(Allocator &a, const pointer &p)
 | |
|    {  a.deallocate(p, 1);   }
 | |
| 
 | |
|    static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
 | |
|    {
 | |
|       size_type n = holder.size();
 | |
|       typename multiallocation_chain::iterator it = holder.begin();
 | |
|       while(n--){
 | |
|          pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
 | |
|          ++it;
 | |
|          a.deallocate(p, 1);
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    struct allocate_individual_rollback
 | |
|    {
 | |
|       allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
 | |
|          : mr_a(a), mp_chain(&chain)
 | |
|       {}
 | |
| 
 | |
|       ~allocate_individual_rollback()
 | |
|       {
 | |
|          if(mp_chain)
 | |
|             allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
 | |
|       }
 | |
| 
 | |
|       void release()
 | |
|       {
 | |
|          mp_chain = 0;
 | |
|       }
 | |
| 
 | |
|       Allocator &mr_a;
 | |
|       multiallocation_chain * mp_chain;
 | |
|    };
 | |
| 
 | |
|    static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
 | |
|    {
 | |
|       allocate_individual_rollback rollback(a, m);
 | |
|       while(n--){
 | |
|          m.push_front(a.allocate(1));
 | |
|       }
 | |
|       rollback.release();
 | |
|    }
 | |
| 
 | |
|    static pointer allocation_command(Allocator &a, allocation_type command,
 | |
|                          size_type, size_type &prefer_in_recvd_out_size, pointer &reuse)
 | |
|    {
 | |
|       pointer ret = pointer();
 | |
|       if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){
 | |
|          throw_logic_error("version 1 allocator without allocate_new flag");
 | |
|       }
 | |
|       else{
 | |
|          BOOST_TRY{
 | |
|             ret = a.allocate(prefer_in_recvd_out_size);
 | |
|          }
 | |
|          BOOST_CATCH(...){
 | |
|             if(!(command & nothrow_allocation)){
 | |
|                BOOST_RETHROW
 | |
|             }
 | |
|          }
 | |
|          BOOST_CATCH_END
 | |
|          reuse = pointer();
 | |
|       }
 | |
|       return ret;
 | |
|    }
 | |
| };
 | |
| 
 | |
| }  //namespace container_detail {
 | |
| }  //namespace container {
 | |
| }  //namespace boost {
 | |
| 
 | |
| #include <boost/container/detail/config_end.hpp>
 | |
| 
 | |
| #endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
 | 
