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