]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2005-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_MULTIALLOCATION_CHAIN_HPP | |
12 | #define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_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 | // container | |
25 | #include <boost/container/container_fwd.hpp> | |
26 | // container/detail | |
b32b8144 | 27 | #include <boost/move/detail/to_raw_pointer.hpp> |
7c673cae FG |
28 | #include <boost/container/detail/transform_iterator.hpp> |
29 | #include <boost/container/detail/type_traits.hpp> | |
30 | // intrusive | |
31 | #include <boost/intrusive/slist.hpp> | |
32 | #include <boost/intrusive/pointer_traits.hpp> | |
33 | // move | |
34 | #include <boost/move/utility_core.hpp> | |
35 | ||
36 | namespace boost { | |
37 | namespace container { | |
38 | namespace container_detail { | |
39 | ||
40 | template<class VoidPointer> | |
41 | class basic_multiallocation_chain | |
42 | { | |
43 | private: | |
44 | typedef bi::slist_base_hook<bi::void_pointer<VoidPointer> | |
45 | ,bi::link_mode<bi::normal_link> | |
46 | > node; | |
47 | ||
48 | typedef typename boost::intrusive::pointer_traits | |
49 | <VoidPointer>::template rebind_pointer<char>::type char_ptr; | |
50 | typedef typename boost::intrusive:: | |
51 | pointer_traits<char_ptr>::difference_type difference_type; | |
52 | ||
53 | typedef bi::slist< node | |
54 | , bi::linear<true> | |
55 | , bi::cache_last<true> | |
56 | , bi::size_type<typename boost::container::container_detail::make_unsigned<difference_type>::type> | |
57 | > slist_impl_t; | |
58 | slist_impl_t slist_impl_; | |
59 | ||
60 | typedef typename boost::intrusive::pointer_traits | |
61 | <VoidPointer>::template rebind_pointer<node>::type node_ptr; | |
62 | typedef typename boost::intrusive:: | |
63 | pointer_traits<node_ptr> node_ptr_traits; | |
64 | ||
65 | static node & to_node(const VoidPointer &p) | |
b32b8144 | 66 | { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); } |
7c673cae FG |
67 | |
68 | static VoidPointer from_node(node &n) | |
69 | { return node_ptr_traits::pointer_to(n); } | |
70 | ||
71 | static node_ptr to_node_ptr(const VoidPointer &p) | |
72 | { return node_ptr_traits::static_cast_from(p); } | |
73 | ||
74 | BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) | |
75 | ||
76 | public: | |
77 | ||
78 | typedef VoidPointer void_pointer; | |
79 | typedef typename slist_impl_t::iterator iterator; | |
80 | typedef typename slist_impl_t::size_type size_type; | |
81 | ||
82 | basic_multiallocation_chain() | |
83 | : slist_impl_() | |
84 | {} | |
85 | ||
86 | basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n) | |
87 | : slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n) | |
88 | {} | |
89 | ||
90 | basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) | |
91 | : slist_impl_(::boost::move(other.slist_impl_)) | |
92 | {} | |
93 | ||
94 | basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) | |
95 | { | |
96 | slist_impl_ = ::boost::move(other.slist_impl_); | |
97 | return *this; | |
98 | } | |
99 | ||
100 | bool empty() const | |
101 | { return slist_impl_.empty(); } | |
102 | ||
103 | size_type size() const | |
104 | { return slist_impl_.size(); } | |
105 | ||
106 | iterator before_begin() | |
107 | { return slist_impl_.before_begin(); } | |
108 | ||
109 | iterator begin() | |
110 | { return slist_impl_.begin(); } | |
111 | ||
112 | iterator end() | |
113 | { return slist_impl_.end(); } | |
114 | ||
115 | iterator last() | |
116 | { return slist_impl_.last(); } | |
117 | ||
118 | void clear() | |
119 | { slist_impl_.clear(); } | |
120 | ||
121 | iterator insert_after(iterator it, void_pointer m) | |
122 | { return slist_impl_.insert_after(it, to_node(m)); } | |
123 | ||
124 | void push_front(const void_pointer &m) | |
125 | { return slist_impl_.push_front(to_node(m)); } | |
126 | ||
127 | void push_back(const void_pointer &m) | |
128 | { return slist_impl_.push_back(to_node(m)); } | |
129 | ||
130 | void_pointer pop_front() | |
131 | { | |
132 | node & n = slist_impl_.front(); | |
133 | void_pointer ret = from_node(n); | |
134 | slist_impl_.pop_front(); | |
135 | return ret; | |
136 | } | |
137 | ||
138 | void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n) | |
139 | { slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); } | |
140 | ||
141 | void splice_after(iterator after_this, basic_multiallocation_chain &x) | |
142 | { slist_impl_.splice_after(after_this, x.slist_impl_); } | |
143 | ||
144 | void erase_after(iterator before_b, iterator e, size_type n) | |
145 | { slist_impl_.erase_after(before_b, e, n); } | |
146 | ||
147 | void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units) | |
148 | { | |
149 | typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits; | |
150 | char_ptr elem = char_pointer_traits::static_cast_from(b); | |
151 | if(num_units){ | |
152 | char_ptr prev_elem = elem; | |
153 | elem += unit_bytes; | |
154 | for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){ | |
b32b8144 | 155 | ::new (boost::movelib::to_raw_pointer(prev_elem)) void_pointer(elem); |
7c673cae FG |
156 | prev_elem = elem; |
157 | } | |
158 | slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units); | |
159 | } | |
160 | return elem; | |
161 | } | |
162 | ||
163 | void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n) | |
164 | { slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); } | |
165 | ||
166 | void swap(basic_multiallocation_chain &x) | |
167 | { slist_impl_.swap(x.slist_impl_); } | |
168 | ||
169 | static iterator iterator_to(const void_pointer &p) | |
170 | { return slist_impl_t::s_iterator_to(to_node(p)); } | |
171 | ||
172 | std::pair<void_pointer, void_pointer> extract_data() | |
173 | { | |
174 | std::pair<void_pointer, void_pointer> ret | |
175 | (slist_impl_.begin().operator->() | |
176 | ,slist_impl_.last().operator->()); | |
177 | slist_impl_.clear(); | |
178 | return ret; | |
179 | } | |
180 | }; | |
181 | ||
182 | template<class T> | |
183 | struct cast_functor | |
184 | { | |
185 | typedef typename container_detail::add_reference<T>::type result_type; | |
186 | template<class U> | |
187 | result_type operator()(U &ptr) const | |
188 | { return *static_cast<T*>(static_cast<void*>(&ptr)); } | |
189 | }; | |
190 | ||
191 | template<class MultiallocationChain, class T> | |
192 | class transform_multiallocation_chain | |
193 | : public MultiallocationChain | |
194 | { | |
195 | private: | |
196 | BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain) | |
197 | //transform_multiallocation_chain(const transform_multiallocation_chain &); | |
198 | //transform_multiallocation_chain & operator=(const transform_multiallocation_chain &); | |
199 | ||
200 | typedef typename MultiallocationChain::void_pointer void_pointer; | |
201 | typedef typename boost::intrusive::pointer_traits | |
202 | <void_pointer> void_pointer_traits; | |
203 | typedef typename void_pointer_traits::template | |
204 | rebind_pointer<T>::type pointer; | |
205 | typedef typename boost::intrusive::pointer_traits | |
206 | <pointer> pointer_traits; | |
207 | ||
208 | static pointer cast(const void_pointer &p) | |
209 | { return pointer_traits::static_cast_from(p); } | |
210 | ||
211 | public: | |
212 | typedef transform_iterator | |
213 | < typename MultiallocationChain::iterator | |
214 | , container_detail::cast_functor <T> > iterator; | |
215 | typedef typename MultiallocationChain::size_type size_type; | |
216 | ||
217 | transform_multiallocation_chain() | |
218 | : MultiallocationChain() | |
219 | {} | |
220 | ||
221 | transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other) | |
222 | : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other))) | |
223 | {} | |
224 | ||
225 | transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other) | |
226 | : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other))) | |
227 | {} | |
228 | ||
229 | transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other) | |
230 | { | |
231 | return static_cast<MultiallocationChain&> | |
232 | (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other)))); | |
233 | } | |
234 | /* | |
235 | void push_front(const pointer &mem) | |
236 | { holder_.push_front(mem); } | |
237 | ||
238 | void push_back(const pointer &mem) | |
239 | { return holder_.push_back(mem); } | |
240 | ||
241 | void swap(transform_multiallocation_chain &other_chain) | |
242 | { holder_.swap(other_chain.holder_); } | |
243 | ||
244 | void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n) | |
245 | { holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); } | |
246 | ||
247 | void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n) | |
248 | { holder_.incorporate_after(after_this.base(), b, before_e, n); } | |
249 | */ | |
250 | pointer pop_front() | |
251 | { return cast(this->MultiallocationChain::pop_front()); } | |
252 | /* | |
253 | bool empty() const | |
254 | { return holder_.empty(); } | |
255 | ||
256 | iterator before_begin() | |
257 | { return iterator(holder_.before_begin()); } | |
258 | */ | |
259 | iterator begin() | |
260 | { return iterator(this->MultiallocationChain::begin()); } | |
261 | /* | |
262 | iterator end() | |
263 | { return iterator(holder_.end()); } | |
264 | ||
265 | iterator last() | |
266 | { return iterator(holder_.last()); } | |
267 | ||
268 | size_type size() const | |
269 | { return holder_.size(); } | |
270 | ||
271 | void clear() | |
272 | { holder_.clear(); } | |
273 | */ | |
274 | iterator insert_after(iterator it, pointer m) | |
275 | { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); } | |
276 | ||
277 | static iterator iterator_to(const pointer &p) | |
278 | { return iterator(MultiallocationChain::iterator_to(p)); } | |
279 | ||
280 | std::pair<pointer, pointer> extract_data() | |
281 | { | |
282 | std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data()); | |
283 | return std::pair<pointer, pointer>(cast(data.first), cast(data.second)); | |
284 | } | |
285 | /* | |
286 | MultiallocationChain &extract_multiallocation_chain() | |
287 | { return holder_; }*/ | |
288 | }; | |
289 | ||
290 | }}} | |
291 | ||
292 | // namespace container_detail { | |
293 | // namespace container { | |
294 | // namespace boost { | |
295 | ||
296 | #include <boost/container/detail/config_end.hpp> | |
297 | ||
298 | #endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP |