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 dtl { 37 38 template<class Allocator, unsigned Version = boost::container::dtl::version<Allocator>::value> 39 struct allocator_version_traits 40 { 41 typedef ::boost::container::dtl::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::dtl::allocator_version_traits50 static pointer allocate_one(Allocator &a) 51 { return a.allocate_one(); } 52 deallocate_oneboost::container::dtl::allocator_version_traits53 static void deallocate_one(Allocator &a, const pointer &p) 54 { a.deallocate_one(p); } 55 allocate_individualboost::container::dtl::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::dtl::allocator_version_traits59 static void deallocate_individual(Allocator &a, multiallocation_chain &holder) 60 { a.deallocate_individual(holder); } 61 allocation_commandboost::container::dtl::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::dtl::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 dtl::basic_multiallocation_chain 80 <void_ptr> multialloc_cached_counted; 81 typedef boost::container::dtl:: 82 transform_multiallocation_chain 83 < multialloc_cached_counted, value_type> multiallocation_chain; 84 85 //Node allocation interface allocate_oneboost::container::dtl::allocator_version_traits86 static pointer allocate_one(Allocator &a) 87 { return a.allocate(1); } 88 deallocate_oneboost::container::dtl::allocator_version_traits89 static void deallocate_one(Allocator &a, const pointer &p) 90 { a.deallocate(p, 1); } 91 deallocate_individualboost::container::dtl::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 --n; 98 pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it); 99 ++it; 100 a.deallocate(p, 1); 101 } 102 } 103 104 struct allocate_individual_rollback 105 { allocate_individual_rollbackboost::container::dtl::allocator_version_traits::allocate_individual_rollback106 allocate_individual_rollback(Allocator &a, multiallocation_chain &chain) 107 : mr_a(a), mp_chain(&chain) 108 {} 109 ~allocate_individual_rollbackboost::container::dtl::allocator_version_traits::allocate_individual_rollback110 ~allocate_individual_rollback() 111 { 112 if(mp_chain) 113 allocator_version_traits::deallocate_individual(mr_a, *mp_chain); 114 } 115 releaseboost::container::dtl::allocator_version_traits::allocate_individual_rollback116 void release() 117 { 118 mp_chain = 0; 119 } 120 121 Allocator &mr_a; 122 multiallocation_chain * mp_chain; 123 }; 124 allocate_individualboost::container::dtl::allocator_version_traits125 static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m) 126 { 127 allocate_individual_rollback rollback(a, m); 128 while(n--){ 129 m.push_front(a.allocate(1)); 130 } 131 rollback.release(); 132 } 133 allocation_commandboost::container::dtl::allocator_version_traits134 static pointer allocation_command(Allocator &a, allocation_type command, 135 size_type, size_type &prefer_in_recvd_out_size, pointer &reuse) 136 { 137 pointer ret = pointer(); 138 if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){ 139 throw_logic_error("version 1 allocator without allocate_new flag"); 140 } 141 else{ 142 BOOST_TRY{ 143 ret = a.allocate(prefer_in_recvd_out_size); 144 } 145 BOOST_CATCH(...){ 146 if(!(command & nothrow_allocation)){ 147 BOOST_RETHROW 148 } 149 } 150 BOOST_CATCH_END 151 reuse = pointer(); 152 } 153 return ret; 154 } 155 }; 156 157 } //namespace dtl { 158 } //namespace container { 159 } //namespace boost { 160 161 #include <boost/container/detail/config_end.hpp> 162 163 #endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP) 164