1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2012-2013. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/container for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 11 #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP 12 #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP 13 14 #ifndef BOOST_CONFIG_HPP 15 # include <boost/config.hpp> 16 #endif 17 18 #if defined(BOOST_HAS_PRAGMA_ONCE) 19 # pragma once 20 #endif 21 22 #include <boost/container/detail/config_begin.hpp> 23 #include <boost/container/detail/workaround.hpp> 24 25 #include <boost/container/allocator_traits.hpp> //allocator_traits 26 #include <boost/container/throw_exception.hpp> 27 #include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain 28 #include <boost/container/detail/version_type.hpp> //version_type 29 #include <boost/container/detail/allocation_type.hpp> //allocation_type 30 #include <boost/container/detail/mpl.hpp> //integral_constant 31 #include <boost/intrusive/pointer_traits.hpp> //pointer_traits 32 #include <boost/core/no_exceptions_support.hpp> //BOOST_TRY 33 34 namespace boost { 35 namespace container { 36 namespace container_detail { 37 38 template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value> 39 struct allocator_version_traits 40 { 41 typedef ::boost::container::container_detail::integral_constant 42 <unsigned, Version> alloc_version; 43 44 typedef typename Allocator::multiallocation_chain multiallocation_chain; 45 46 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; 47 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type; 48 49 //Node allocation interface allocate_oneboost::container::container_detail::allocator_version_traits50 static pointer allocate_one(Allocator &a) 51 { return a.allocate_one(); } 52 deallocate_oneboost::container::container_detail::allocator_version_traits53 static void deallocate_one(Allocator &a, const pointer &p) 54 { a.deallocate_one(p); } 55 allocate_individualboost::container::container_detail::allocator_version_traits56 static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m) 57 { return a.allocate_individual(n, m); } 58 deallocate_individualboost::container::container_detail::allocator_version_traits59 static void deallocate_individual(Allocator &a, multiallocation_chain &holder) 60 { a.deallocate_individual(holder); } 61 allocation_commandboost::container::container_detail::allocator_version_traits62 static pointer allocation_command(Allocator &a, allocation_type command, 63 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) 64 { return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } 65 }; 66 67 template<class Allocator> 68 struct allocator_version_traits<Allocator, 1> 69 { 70 typedef ::boost::container::container_detail::integral_constant 71 <unsigned, 1> alloc_version; 72 73 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; 74 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type; 75 typedef typename boost::container::allocator_traits<Allocator>::value_type value_type; 76 77 typedef typename boost::intrusive::pointer_traits<pointer>:: 78 template rebind_pointer<void>::type void_ptr; 79 typedef container_detail::basic_multiallocation_chain 80 <void_ptr> multialloc_cached_counted; 81 typedef boost::container::container_detail:: 82 transform_multiallocation_chain 83 < multialloc_cached_counted, value_type> multiallocation_chain; 84 85 //Node allocation interface allocate_oneboost::container::container_detail::allocator_version_traits86 static pointer allocate_one(Allocator &a) 87 { return a.allocate(1); } 88 deallocate_oneboost::container::container_detail::allocator_version_traits89 static void deallocate_one(Allocator &a, const pointer &p) 90 { a.deallocate(p, 1); } 91 deallocate_individualboost::container::container_detail::allocator_version_traits92 static void deallocate_individual(Allocator &a, multiallocation_chain &holder) 93 { 94 size_type n = holder.size(); 95 typename multiallocation_chain::iterator it = holder.begin(); 96 while(n--){ 97 pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it); 98 ++it; 99 a.deallocate(p, 1); 100 } 101 } 102 103 struct allocate_individual_rollback 104 { allocate_individual_rollbackboost::container::container_detail::allocator_version_traits::allocate_individual_rollback105 allocate_individual_rollback(Allocator &a, multiallocation_chain &chain) 106 : mr_a(a), mp_chain(&chain) 107 {} 108 ~allocate_individual_rollbackboost::container::container_detail::allocator_version_traits::allocate_individual_rollback109 ~allocate_individual_rollback() 110 { 111 if(mp_chain) 112 allocator_version_traits::deallocate_individual(mr_a, *mp_chain); 113 } 114 releaseboost::container::container_detail::allocator_version_traits::allocate_individual_rollback115 void release() 116 { 117 mp_chain = 0; 118 } 119 120 Allocator &mr_a; 121 multiallocation_chain * mp_chain; 122 }; 123 allocate_individualboost::container::container_detail::allocator_version_traits124 static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m) 125 { 126 allocate_individual_rollback rollback(a, m); 127 while(n--){ 128 m.push_front(a.allocate(1)); 129 } 130 rollback.release(); 131 } 132 allocation_commandboost::container::container_detail::allocator_version_traits133 static pointer allocation_command(Allocator &a, allocation_type command, 134 size_type, size_type &prefer_in_recvd_out_size, pointer &reuse) 135 { 136 pointer ret = pointer(); 137 if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){ 138 throw_logic_error("version 1 allocator without allocate_new flag"); 139 } 140 else{ 141 BOOST_TRY{ 142 ret = a.allocate(prefer_in_recvd_out_size); 143 } 144 BOOST_CATCH(...){ 145 if(!(command & nothrow_allocation)){ 146 BOOST_RETHROW 147 } 148 } 149 BOOST_CATCH_END 150 reuse = pointer(); 151 } 152 return ret; 153 } 154 }; 155 156 } //namespace container_detail { 157 } //namespace container { 158 } //namespace boost { 159 160 #include <boost/container/detail/config_end.hpp> 161 162 #endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP) 163