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) |