File indexing completed on 2025-01-18 09:30:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP
0012 #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_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
0025 #include <boost/container/allocator_traits.hpp> //allocator_traits
0026 #include <boost/container/throw_exception.hpp>
0027 #include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
0028 #include <boost/container/detail/version_type.hpp> //version_type
0029 #include <boost/container/detail/allocation_type.hpp> //allocation_type
0030 #include <boost/container/detail/mpl.hpp> //integral_constant
0031 #include <boost/intrusive/pointer_traits.hpp> //pointer_traits
0032
0033 namespace boost {
0034 namespace container {
0035 namespace dtl {
0036
0037 template<class Allocator, unsigned Version = boost::container::dtl::version<Allocator>::value>
0038 struct allocator_version_traits
0039 {
0040 typedef ::boost::container::dtl::integral_constant
0041 <unsigned, Version> alloc_version;
0042
0043 typedef typename Allocator::multiallocation_chain multiallocation_chain;
0044
0045 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
0046 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
0047
0048
0049 BOOST_CONTAINER_FORCEINLINE static pointer allocate_one(Allocator &a)
0050 { return a.allocate_one(); }
0051
0052 BOOST_CONTAINER_FORCEINLINE static void deallocate_one(Allocator &a, const pointer &p)
0053 { a.deallocate_one(p); }
0054
0055 BOOST_CONTAINER_FORCEINLINE static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
0056 { return a.allocate_individual(n, m); }
0057
0058 BOOST_CONTAINER_FORCEINLINE static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
0059 { a.deallocate_individual(holder); }
0060
0061 BOOST_CONTAINER_FORCEINLINE static pointer allocation_command(Allocator &a, allocation_type command,
0062 size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
0063 { return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
0064 };
0065
0066 template<class Allocator>
0067 struct allocator_version_traits<Allocator, 1>
0068 {
0069 typedef ::boost::container::dtl::integral_constant
0070 <unsigned, 1> alloc_version;
0071
0072 typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
0073 typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
0074 typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
0075
0076 typedef typename boost::intrusive::pointer_traits<pointer>::
0077 template rebind_pointer<void>::type void_ptr;
0078 typedef dtl::basic_multiallocation_chain
0079 <void_ptr> multialloc_cached_counted;
0080 typedef boost::container::dtl::
0081 transform_multiallocation_chain
0082 < multialloc_cached_counted, value_type> multiallocation_chain;
0083
0084
0085 BOOST_CONTAINER_FORCEINLINE static pointer allocate_one(Allocator &a)
0086 { return a.allocate(1); }
0087
0088 BOOST_CONTAINER_FORCEINLINE static void deallocate_one(Allocator &a, const pointer &p)
0089 { a.deallocate(p, 1); }
0090
0091 static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
0092 {
0093 size_type n = holder.size();
0094 typename multiallocation_chain::iterator it = holder.begin();
0095 while(n){
0096 --n;
0097 pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
0098 ++it;
0099 a.deallocate(p, 1);
0100 }
0101 }
0102
0103 struct allocate_individual_rollback
0104 {
0105 BOOST_CONTAINER_FORCEINLINE allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
0106 : mr_a(a), mp_chain(&chain)
0107 {}
0108
0109 BOOST_CONTAINER_FORCEINLINE ~allocate_individual_rollback()
0110 {
0111 if(mp_chain)
0112 allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
0113 }
0114
0115 BOOST_CONTAINER_FORCEINLINE void release()
0116 {
0117 mp_chain = 0;
0118 }
0119
0120 Allocator &mr_a;
0121 multiallocation_chain * mp_chain;
0122 };
0123
0124 static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
0125 {
0126 allocate_individual_rollback rollback(a, m);
0127 while(n--){
0128 m.push_front(a.allocate(1));
0129 }
0130 rollback.release();
0131 }
0132
0133 static pointer allocation_command(Allocator &a, allocation_type command,
0134 size_type, size_type &prefer_in_recvd_out_size, pointer &reuse)
0135 {
0136 pointer ret = pointer();
0137 if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){
0138 throw_logic_error("version 1 allocator without allocate_new flag");
0139 }
0140 else{
0141 BOOST_CONTAINER_TRY{
0142 ret = a.allocate(prefer_in_recvd_out_size);
0143 }
0144 BOOST_CONTAINER_CATCH(...){
0145 if(!(command & nothrow_allocation)){
0146 BOOST_CONTAINER_RETHROW
0147 }
0148 }
0149 BOOST_CONTAINER_CATCH_END
0150 reuse = pointer();
0151 }
0152 return ret;
0153 }
0154 };
0155
0156 }
0157 }
0158 }
0159
0160 #include <boost/container/detail/config_end.hpp>
0161
0162 #endif