1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2005-2008. 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)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #ifndef BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
12 #define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP
14 #include <boost/interprocess/containers/container/detail/config_begin.hpp>
15 #include <boost/interprocess/containers/container/detail/utilities.hpp>
16 #include <boost/interprocess/containers/container/detail/type_traits.hpp>
17 #include <boost/interprocess/containers/container/detail/transform_iterator.hpp>
20 namespace interprocess_container
{
21 namespace containers_detail
{
23 template<class VoidPointer
>
24 class basic_multiallocation_slist
27 typedef VoidPointer void_pointer
;
30 static VoidPointer
&priv_get_ref(const VoidPointer
&p
)
31 { return *static_cast<void_pointer
*>(containers_detail::get_pointer(p
)); }
33 basic_multiallocation_slist(basic_multiallocation_slist
&);
34 basic_multiallocation_slist
&operator=(basic_multiallocation_slist
&);
37 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist
)
39 //!This iterator is returned by "allocate_many" functions so that
40 //!the user can access the multiple buffers allocated in a single call
42 : public std::iterator
<std::input_iterator_tag
, char>
44 friend class basic_multiallocation_slist
<void_pointer
>;
45 void unspecified_bool_type_func() const {}
46 typedef void (iterator::*unspecified_bool_type
)() const;
48 iterator(void_pointer node_range
)
49 : next_node_(node_range
)
53 typedef char value_type
;
54 typedef value_type
& reference
;
55 typedef value_type
* pointer
;
61 iterator
&operator=(const iterator
&other
)
62 { next_node_
= other
.next_node_
; return *this; }
65 iterator
& operator++()
67 next_node_
= *static_cast<void_pointer
*>(containers_detail::get_pointer(next_node_
));
71 iterator
operator++(int)
73 iterator
result(*this);
78 bool operator== (const iterator
& other
) const
79 { return next_node_
== other
.next_node_
; }
81 bool operator!= (const iterator
& other
) const
82 { return !operator== (other
); }
84 reference
operator*() const
85 { return *static_cast<char*>(containers_detail::get_pointer(next_node_
)); }
87 operator unspecified_bool_type() const
88 { return next_node_
? &iterator::unspecified_bool_type_func
: 0; }
90 pointer
operator->() const
91 { return &(*(*this)); }
94 void_pointer next_node_
;
101 basic_multiallocation_slist()
105 basic_multiallocation_slist(void_pointer p
)
106 : it_(p
? iterator_to(p
) : iterator())
109 basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist
) other
)
111 { this->swap(other
); }
113 basic_multiallocation_slist
& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist
) other
)
115 basic_multiallocation_slist
tmp(boost::interprocess::move(other
));
123 iterator
before_begin() const
124 { return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_
.next_node_
)))); }
126 iterator
begin() const
130 { return iterator(); }
133 { this->it_
.next_node_
= void_pointer(0); }
135 iterator
insert_after(iterator it
, void_pointer m
)
137 priv_get_ref(m
) = priv_get_ref(it
.next_node_
);
138 priv_get_ref(it
.next_node_
) = m
;
142 void push_front(void_pointer m
)
144 priv_get_ref(m
) = this->it_
.next_node_
;
145 this->it_
.next_node_
= m
;
152 { return containers_detail::get_pointer(it_
.next_node_
); }
154 void splice_after(iterator after_this
, iterator before_begin
, iterator before_end
)
156 if (after_this
!= before_begin
&& after_this
!= before_end
&& before_begin
!= before_end
) {
157 void_pointer next_b
= priv_get_ref(before_begin
.next_node_
);
158 void_pointer next_e
= priv_get_ref(before_end
.next_node_
);
159 void_pointer next_p
= priv_get_ref(after_this
.next_node_
);
160 priv_get_ref(before_begin
.next_node_
) = next_e
;
161 priv_get_ref(before_end
.next_node_
) = next_p
;
162 priv_get_ref(after_this
.next_node_
) = next_b
;
166 void swap(basic_multiallocation_slist
&other_chain
)
168 std::swap(this->it_
, other_chain
.it_
);
171 static iterator
iterator_to(void_pointer p
)
172 { return iterator(p
); }
174 void_pointer
extract_data()
176 void_pointer ret
= empty() ? void_pointer(0) : void_pointer(&*it_
);
182 template<class VoidPointer
>
183 class basic_multiallocation_cached_slist
186 basic_multiallocation_slist
<VoidPointer
> slist_
;
187 typename basic_multiallocation_slist
<VoidPointer
>::iterator last_
;
189 basic_multiallocation_cached_slist(basic_multiallocation_cached_slist
&);
190 basic_multiallocation_cached_slist
&operator=(basic_multiallocation_cached_slist
&);
193 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist
)
195 typedef typename basic_multiallocation_slist
<VoidPointer
>::void_pointer void_pointer
;
196 typedef typename basic_multiallocation_slist
<VoidPointer
>::iterator iterator
;
198 basic_multiallocation_cached_slist()
199 : slist_(), last_(slist_
.before_begin())
202 basic_multiallocation_cached_slist(iterator first_node)
203 : slist_(first_node), last_(slist_.before_begin())
206 while(first_node != end){
211 basic_multiallocation_cached_slist(void_pointer p1
, void_pointer p2
)
212 : slist_(p1
), last_(p2
? iterator_to(p2
) : slist_
.before_begin())
215 basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist
) other
)
216 : slist_(), last_(slist_
.before_begin())
217 { this->swap(other
); }
219 basic_multiallocation_cached_slist
& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist
) other
)
221 basic_multiallocation_cached_slist
tmp(boost::interprocess::move(other
));
227 { return slist_
.empty(); }
229 iterator
before_begin() const
230 { return slist_
.before_begin(); }
232 iterator
begin() const
233 { return slist_
.begin(); }
236 { return slist_
.end(); }
238 iterator
last() const
244 last_
= slist_
.before_begin();
247 iterator
insert_after(iterator it
, void_pointer m
)
249 slist_
.insert_after(it
, m
);
251 last_
= slist_
.iterator_to(m
);
253 return iterator_to(m
);
256 void push_front(void_pointer m
)
257 { this->insert_after(this->before_begin(), m
); }
259 void push_back(void_pointer m
)
260 { this->insert_after(last_
, m
); }
264 if(last_
== slist_
.begin()){
265 last_
= slist_
.before_begin();
271 { return slist_
.front(); }
273 void splice_after(iterator after_this
, iterator before_begin
, iterator before_end
)
275 if(before_begin
== before_end
)
277 if(after_this
== last_
){
280 slist_
.splice_after(after_this
, before_begin
, before_end
);
283 void swap(basic_multiallocation_cached_slist
&x
)
285 slist_
.swap(x
.slist_
);
287 swap(last_
, x
.last_
);
288 if(last_
== x
.before_begin()){
289 last_
= this->before_begin();
291 if(x
.last_
== this->before_begin()){
292 x
.last_
= x
.before_begin();
296 static iterator
iterator_to(void_pointer p
)
297 { return basic_multiallocation_slist
<VoidPointer
>::iterator_to(p
); }
299 std::pair
<void_pointer
, void_pointer
> extract_data()
302 return std::pair
<void_pointer
, void_pointer
>(void_pointer(0), void_pointer(0));
305 void_pointer p1
= slist_
.extract_data();
306 void_pointer p2
= void_pointer(&*last_
);
308 return std::pair
<void_pointer
, void_pointer
>(p1
, p2
);
313 template<class MultiallocatorCachedSlist
>
314 class basic_multiallocation_cached_counted_slist
317 MultiallocatorCachedSlist cached_slist_
;
320 basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist
&);
321 basic_multiallocation_cached_counted_slist
&operator=(basic_multiallocation_cached_counted_slist
&);
324 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist
)
326 typedef typename
MultiallocatorCachedSlist::void_pointer void_pointer
;
327 typedef typename
MultiallocatorCachedSlist::iterator iterator
;
329 basic_multiallocation_cached_counted_slist()
330 : cached_slist_(), size_(0)
333 basic_multiallocation_cached_counted_slist(void_pointer p1
, void_pointer p2
, std::size_t n
)
334 : cached_slist_(p1
, p2
), size_(n
)
337 basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist
) other
)
338 : cached_slist_(), size_(0)
339 { this->swap(other
); }
341 basic_multiallocation_cached_counted_slist
& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist
) other
)
343 basic_multiallocation_cached_counted_slist
tmp(boost::interprocess::move(other
));
348 basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem
, std::size_t n
)
349 : cached_slist_(boost::interprocess::move(mem
)), size_(n
)
353 { return cached_slist_
.empty(); }
355 std::size_t size() const
358 iterator
before_begin() const
359 { return cached_slist_
.before_begin(); }
361 iterator
begin() const
362 { return cached_slist_
.begin(); }
365 { return cached_slist_
.end(); }
367 iterator
last() const
368 { return cached_slist_
.last(); }
372 cached_slist_
.clear();
376 iterator
insert_after(iterator it
, void_pointer m
)
378 iterator ret
= cached_slist_
.insert_after(it
, m
);
383 void push_front(void_pointer m
)
384 { this->insert_after(this->before_begin(), m
); }
386 void push_back(void_pointer m
)
387 { this->insert_after(this->before_begin(), m
); }
391 cached_slist_
.pop_front();
396 { return cached_slist_
.front(); }
398 void splice_after(iterator after_this
, basic_multiallocation_cached_counted_slist
&x
, iterator before_begin
, iterator before_end
)
400 std::size_t n
= static_cast<std::size_t>(std::distance(before_begin
, before_end
));
401 this->splice_after(after_this
, x
, before_begin
, before_end
, n
);
404 void splice_after(iterator after_this
, basic_multiallocation_cached_counted_slist
&x
, iterator before_begin
, iterator before_end
, std::size_t n
)
406 cached_slist_
.splice_after(after_this
, before_begin
, before_end
);
411 void splice_after(iterator after_this
, basic_multiallocation_cached_counted_slist
&x
)
413 cached_slist_
.splice_after(after_this
, x
.before_begin(), x
.last());
418 void swap(basic_multiallocation_cached_counted_slist
&x
)
420 cached_slist_
.swap(x
.cached_slist_
);
422 swap(size_
, x
.size_
);
425 static iterator
iterator_to(void_pointer p
)
426 { return MultiallocatorCachedSlist::iterator_to(p
); }
428 std::pair
<void_pointer
, void_pointer
> extract_data()
431 return cached_slist_
.extract_data();
438 typedef typename
containers_detail::add_reference
<T
>::type result_type
;
439 result_type
operator()(char &ptr
) const
440 { return *static_cast<T
*>(static_cast<void*>(&ptr
)); }
444 template<class MultiallocationChain
, class T
>
445 class transform_multiallocation_chain
449 MultiallocationChain holder_
;
450 typedef typename
MultiallocationChain::void_pointer void_pointer
;
451 typedef typename
boost::pointer_to_other
452 <void_pointer
, T
>::type pointer
;
454 transform_multiallocation_chain(transform_multiallocation_chain
&);
455 transform_multiallocation_chain
&operator=(transform_multiallocation_chain
&);
457 static pointer
cast(void_pointer p
)
459 return pointer(static_cast<T
*>(containers_detail::get_pointer(p
)));
463 BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain
)
465 typedef transform_iterator
466 < typename
MultiallocationChain::iterator
467 , containers_detail::cast_functor
<T
> > iterator
;
469 transform_multiallocation_chain(void_pointer p1
, void_pointer p2
, std::size_t n
)
473 transform_multiallocation_chain()
477 transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain
) other
)
479 { this->swap(other
); }
481 transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain
) other
)
482 : holder_(boost::interprocess::move(other
))
485 transform_multiallocation_chain
& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain
) other
)
487 transform_multiallocation_chain
tmp(boost::interprocess::move(other
));
492 void push_front(pointer mem
)
493 { holder_
.push_front(mem
); }
495 void swap(transform_multiallocation_chain
&other_chain
)
496 { holder_
.swap(other_chain
.holder_
); }
498 void splice_after(iterator after_this, iterator before_begin, iterator before_end)
499 { holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); }
501 void splice_after(iterator after_this
, transform_multiallocation_chain
&x
, iterator before_begin
, iterator before_end
, std::size_t n
)
502 { holder_
.splice_after(after_this
.base(), x
.holder_
, before_begin
.base(), before_end
.base(), n
); }
505 { holder_
.pop_front(); }
507 pointer
front() const
508 { return cast(holder_
.front()); }
511 { return holder_
.empty(); }
513 iterator
before_begin() const
514 { return iterator(holder_
.before_begin()); }
516 iterator
begin() const
517 { return iterator(holder_
.begin()); }
520 { return iterator(holder_
.end()); }
522 iterator
last() const
523 { return iterator(holder_
.last()); }
525 std::size_t size() const
526 { return holder_
.size(); }
531 iterator
insert_after(iterator it
, pointer m
)
532 { return iterator(holder_
.insert_after(it
.base(), m
)); }
534 static iterator
iterator_to(pointer p
)
535 { return iterator(MultiallocationChain::iterator_to(p
)); }
537 std::pair
<void_pointer
, void_pointer
> extract_data()
538 { return holder_
.extract_data(); }
540 MultiallocationChain
extract_multiallocation_chain()
542 return MultiallocationChain(boost::interprocess::move(holder_
));
548 // namespace containers_detail {
549 // namespace interprocess_container {
552 #include <boost/interprocess/containers/container/detail/config_end.hpp>
554 #endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP