| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2005-2008. Distributed under the Boost |
| // Software License, Version 1.0. (See accompanying file |
| // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // See http://www.boost.org/libs/container for documentation. |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| #ifndef BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP |
| #define BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP |
| |
| #include <boost/interprocess/containers/container/detail/config_begin.hpp> |
| #include <boost/interprocess/containers/container/detail/utilities.hpp> |
| #include <boost/interprocess/containers/container/detail/type_traits.hpp> |
| #include <boost/interprocess/containers/container/detail/transform_iterator.hpp> |
| |
| namespace boost { |
| namespace interprocess_container { |
| namespace containers_detail { |
| |
| template<class VoidPointer> |
| class basic_multiallocation_slist |
| { |
| public: |
| typedef VoidPointer void_pointer; |
| |
| private: |
| static VoidPointer &priv_get_ref(const VoidPointer &p) |
| { return *static_cast<void_pointer*>(containers_detail::get_pointer(p)); } |
| |
| basic_multiallocation_slist(basic_multiallocation_slist &); |
| basic_multiallocation_slist &operator=(basic_multiallocation_slist &); |
| |
| public: |
| BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_slist) |
| |
| //!This iterator is returned by "allocate_many" functions so that |
| //!the user can access the multiple buffers allocated in a single call |
| class iterator |
| : public std::iterator<std::input_iterator_tag, char> |
| { |
| friend class basic_multiallocation_slist<void_pointer>; |
| void unspecified_bool_type_func() const {} |
| typedef void (iterator::*unspecified_bool_type)() const; |
| |
| iterator(void_pointer node_range) |
| : next_node_(node_range) |
| {} |
| |
| public: |
| typedef char value_type; |
| typedef value_type & reference; |
| typedef value_type * pointer; |
| |
| iterator() |
| : next_node_(0) |
| {} |
| |
| iterator &operator=(const iterator &other) |
| { next_node_ = other.next_node_; return *this; } |
| |
| public: |
| iterator& operator++() |
| { |
| next_node_ = *static_cast<void_pointer*>(containers_detail::get_pointer(next_node_)); |
| return *this; |
| } |
| |
| iterator operator++(int) |
| { |
| iterator result(*this); |
| ++*this; |
| return result; |
| } |
| |
| bool operator== (const iterator& other) const |
| { return next_node_ == other.next_node_; } |
| |
| bool operator!= (const iterator& other) const |
| { return !operator== (other); } |
| |
| reference operator*() const |
| { return *static_cast<char*>(containers_detail::get_pointer(next_node_)); } |
| |
| operator unspecified_bool_type() const |
| { return next_node_? &iterator::unspecified_bool_type_func : 0; } |
| |
| pointer operator->() const |
| { return &(*(*this)); } |
| |
| private: |
| void_pointer next_node_; |
| }; |
| |
| private: |
| iterator it_; |
| |
| public: |
| basic_multiallocation_slist() |
| : it_(iterator()) |
| {} |
| |
| basic_multiallocation_slist(void_pointer p) |
| : it_(p ? iterator_to(p) : iterator()) |
| {} |
| |
| basic_multiallocation_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other) |
| : it_(iterator()) |
| { this->swap(other); } |
| |
| basic_multiallocation_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_slist) other) |
| { |
| basic_multiallocation_slist tmp(boost::interprocess::move(other)); |
| this->swap(tmp); |
| return *this; |
| } |
| |
| bool empty() const |
| { return !it_; } |
| |
| iterator before_begin() const |
| { return iterator(void_pointer(const_cast<void*>(static_cast<const void*>(&it_.next_node_)))); } |
| |
| iterator begin() const |
| { return it_; } |
| |
| iterator end() const |
| { return iterator(); } |
| |
| void clear() |
| { this->it_.next_node_ = void_pointer(0); } |
| |
| iterator insert_after(iterator it, void_pointer m) |
| { |
| priv_get_ref(m) = priv_get_ref(it.next_node_); |
| priv_get_ref(it.next_node_) = m; |
| return iterator(m); |
| } |
| |
| void push_front(void_pointer m) |
| { |
| priv_get_ref(m) = this->it_.next_node_; |
| this->it_.next_node_ = m; |
| } |
| |
| void pop_front() |
| { ++it_; } |
| |
| void *front() const |
| { return containers_detail::get_pointer(it_.next_node_); } |
| |
| void splice_after(iterator after_this, iterator before_begin, iterator before_end) |
| { |
| if (after_this != before_begin && after_this != before_end && before_begin != before_end) { |
| void_pointer next_b = priv_get_ref(before_begin.next_node_); |
| void_pointer next_e = priv_get_ref(before_end.next_node_); |
| void_pointer next_p = priv_get_ref(after_this.next_node_); |
| priv_get_ref(before_begin.next_node_) = next_e; |
| priv_get_ref(before_end.next_node_) = next_p; |
| priv_get_ref(after_this.next_node_) = next_b; |
| } |
| } |
| |
| void swap(basic_multiallocation_slist &other_chain) |
| { |
| std::swap(this->it_, other_chain.it_); |
| } |
| |
| static iterator iterator_to(void_pointer p) |
| { return iterator(p); } |
| |
| void_pointer extract_data() |
| { |
| void_pointer ret = empty() ? void_pointer(0) : void_pointer(&*it_); |
| it_ = iterator(); |
| return ret; |
| } |
| }; |
| |
| template<class VoidPointer> |
| class basic_multiallocation_cached_slist |
| { |
| private: |
| basic_multiallocation_slist<VoidPointer> slist_; |
| typename basic_multiallocation_slist<VoidPointer>::iterator last_; |
| |
| basic_multiallocation_cached_slist(basic_multiallocation_cached_slist &); |
| basic_multiallocation_cached_slist &operator=(basic_multiallocation_cached_slist &); |
| |
| public: |
| BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_slist) |
| |
| typedef typename basic_multiallocation_slist<VoidPointer>::void_pointer void_pointer; |
| typedef typename basic_multiallocation_slist<VoidPointer>::iterator iterator; |
| |
| basic_multiallocation_cached_slist() |
| : slist_(), last_(slist_.before_begin()) |
| {} |
| /* |
| basic_multiallocation_cached_slist(iterator first_node) |
| : slist_(first_node), last_(slist_.before_begin()) |
| { |
| iterator end; |
| while(first_node != end){ |
| ++last_; |
| } |
| }*/ |
| |
| basic_multiallocation_cached_slist(void_pointer p1, void_pointer p2) |
| : slist_(p1), last_(p2 ? iterator_to(p2) : slist_.before_begin()) |
| {} |
| |
| basic_multiallocation_cached_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other) |
| : slist_(), last_(slist_.before_begin()) |
| { this->swap(other); } |
| |
| basic_multiallocation_cached_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_slist) other) |
| { |
| basic_multiallocation_cached_slist tmp(boost::interprocess::move(other)); |
| this->swap(tmp); |
| return *this; |
| } |
| |
| bool empty() const |
| { return slist_.empty(); } |
| |
| iterator before_begin() const |
| { return slist_.before_begin(); } |
| |
| iterator begin() const |
| { return slist_.begin(); } |
| |
| iterator end() const |
| { return slist_.end(); } |
| |
| iterator last() const |
| { return last_; } |
| |
| void clear() |
| { |
| slist_.clear(); |
| last_ = slist_.before_begin(); |
| } |
| |
| iterator insert_after(iterator it, void_pointer m) |
| { |
| slist_.insert_after(it, m); |
| if(it == last_){ |
| last_ = slist_.iterator_to(m); |
| } |
| return iterator_to(m); |
| } |
| |
| void push_front(void_pointer m) |
| { this->insert_after(this->before_begin(), m); } |
| |
| void push_back(void_pointer m) |
| { this->insert_after(last_, m); } |
| |
| void pop_front() |
| { |
| if(last_ == slist_.begin()){ |
| last_ = slist_.before_begin(); |
| } |
| slist_.pop_front(); |
| } |
| |
| void *front() const |
| { return slist_.front(); } |
| |
| void splice_after(iterator after_this, iterator before_begin, iterator before_end) |
| { |
| if(before_begin == before_end) |
| return; |
| if(after_this == last_){ |
| last_ = before_end; |
| } |
| slist_.splice_after(after_this, before_begin, before_end); |
| } |
| |
| void swap(basic_multiallocation_cached_slist &x) |
| { |
| slist_.swap(x.slist_); |
| using std::swap; |
| swap(last_, x.last_); |
| if(last_ == x.before_begin()){ |
| last_ = this->before_begin(); |
| } |
| if(x.last_ == this->before_begin()){ |
| x.last_ = x.before_begin(); |
| } |
| } |
| |
| static iterator iterator_to(void_pointer p) |
| { return basic_multiallocation_slist<VoidPointer>::iterator_to(p); } |
| |
| std::pair<void_pointer, void_pointer> extract_data() |
| { |
| if(this->empty()){ |
| return std::pair<void_pointer, void_pointer>(void_pointer(0), void_pointer(0)); |
| } |
| else{ |
| void_pointer p1 = slist_.extract_data(); |
| void_pointer p2 = void_pointer(&*last_); |
| last_ = iterator(); |
| return std::pair<void_pointer, void_pointer>(p1, p2); |
| } |
| } |
| }; |
| |
| template<class MultiallocatorCachedSlist> |
| class basic_multiallocation_cached_counted_slist |
| { |
| private: |
| MultiallocatorCachedSlist cached_slist_; |
| std::size_t size_; |
| |
| basic_multiallocation_cached_counted_slist(basic_multiallocation_cached_counted_slist &); |
| basic_multiallocation_cached_counted_slist &operator=(basic_multiallocation_cached_counted_slist &); |
| |
| public: |
| BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(basic_multiallocation_cached_counted_slist) |
| |
| typedef typename MultiallocatorCachedSlist::void_pointer void_pointer; |
| typedef typename MultiallocatorCachedSlist::iterator iterator; |
| |
| basic_multiallocation_cached_counted_slist() |
| : cached_slist_(), size_(0) |
| {} |
| |
| basic_multiallocation_cached_counted_slist(void_pointer p1, void_pointer p2, std::size_t n) |
| : cached_slist_(p1, p2), size_(n) |
| {} |
| |
| basic_multiallocation_cached_counted_slist(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other) |
| : cached_slist_(), size_(0) |
| { this->swap(other); } |
| |
| basic_multiallocation_cached_counted_slist& operator=(BOOST_INTERPROCESS_RV_REF(basic_multiallocation_cached_counted_slist) other) |
| { |
| basic_multiallocation_cached_counted_slist tmp(boost::interprocess::move(other)); |
| this->swap(tmp); |
| return *this; |
| } |
| |
| basic_multiallocation_cached_counted_slist (MultiallocatorCachedSlist mem, std::size_t n) |
| : cached_slist_(boost::interprocess::move(mem)), size_(n) |
| {} |
| |
| bool empty() const |
| { return cached_slist_.empty(); } |
| |
| std::size_t size() const |
| { return size_; } |
| |
| iterator before_begin() const |
| { return cached_slist_.before_begin(); } |
| |
| iterator begin() const |
| { return cached_slist_.begin(); } |
| |
| iterator end() const |
| { return cached_slist_.end(); } |
| |
| iterator last() const |
| { return cached_slist_.last(); } |
| |
| void clear() |
| { |
| cached_slist_.clear(); |
| size_ = 0; |
| } |
| |
| iterator insert_after(iterator it, void_pointer m) |
| { |
| iterator ret = cached_slist_.insert_after(it, m); |
| ++size_; |
| return ret; |
| } |
| |
| void push_front(void_pointer m) |
| { this->insert_after(this->before_begin(), m); } |
| |
| void push_back(void_pointer m) |
| { this->insert_after(this->before_begin(), m); } |
| |
| void pop_front() |
| { |
| cached_slist_.pop_front(); |
| --size_; |
| } |
| |
| void *front() const |
| { return cached_slist_.front(); } |
| |
| void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end) |
| { |
| std::size_t n = static_cast<std::size_t>(std::distance(before_begin, before_end)); |
| this->splice_after(after_this, x, before_begin, before_end, n); |
| } |
| |
| void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x, iterator before_begin, iterator before_end, std::size_t n) |
| { |
| cached_slist_.splice_after(after_this, before_begin, before_end); |
| size_ += n; |
| x.size_ -= n; |
| } |
| |
| void splice_after(iterator after_this, basic_multiallocation_cached_counted_slist &x) |
| { |
| cached_slist_.splice_after(after_this, x.before_begin(), x.last()); |
| size_ += x.size_; |
| x.size_ = 0; |
| } |
| |
| void swap(basic_multiallocation_cached_counted_slist &x) |
| { |
| cached_slist_.swap(x.cached_slist_); |
| using std::swap; |
| swap(size_, x.size_); |
| } |
| |
| static iterator iterator_to(void_pointer p) |
| { return MultiallocatorCachedSlist::iterator_to(p); } |
| |
| std::pair<void_pointer, void_pointer> extract_data() |
| { |
| size_ = 0; |
| return cached_slist_.extract_data(); |
| } |
| }; |
| |
| template<class T> |
| struct cast_functor |
| { |
| typedef typename containers_detail::add_reference<T>::type result_type; |
| result_type operator()(char &ptr) const |
| { return *static_cast<T*>(static_cast<void*>(&ptr)); } |
| }; |
| |
| |
| template<class MultiallocationChain, class T> |
| class transform_multiallocation_chain |
| { |
| private: |
| |
| MultiallocationChain holder_; |
| typedef typename MultiallocationChain::void_pointer void_pointer; |
| typedef typename boost::pointer_to_other |
| <void_pointer, T>::type pointer; |
| |
| transform_multiallocation_chain(transform_multiallocation_chain &); |
| transform_multiallocation_chain &operator=(transform_multiallocation_chain &); |
| |
| static pointer cast(void_pointer p) |
| { |
| return pointer(static_cast<T*>(containers_detail::get_pointer(p))); |
| } |
| |
| public: |
| BOOST_INTERPROCESS_ENABLE_MOVE_EMULATION(transform_multiallocation_chain) |
| |
| typedef transform_iterator |
| < typename MultiallocationChain::iterator |
| , containers_detail::cast_functor <T> > iterator; |
| |
| transform_multiallocation_chain(void_pointer p1, void_pointer p2, std::size_t n) |
| : holder_(p1, p2, n) |
| {} |
| |
| transform_multiallocation_chain() |
| : holder_() |
| {} |
| |
| transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other) |
| : holder_() |
| { this->swap(other); } |
| |
| transform_multiallocation_chain(BOOST_INTERPROCESS_RV_REF(MultiallocationChain) other) |
| : holder_(boost::interprocess::move(other)) |
| {} |
| |
| transform_multiallocation_chain& operator=(BOOST_INTERPROCESS_RV_REF(transform_multiallocation_chain) other) |
| { |
| transform_multiallocation_chain tmp(boost::interprocess::move(other)); |
| this->swap(tmp); |
| return *this; |
| } |
| |
| void push_front(pointer mem) |
| { holder_.push_front(mem); } |
| |
| void swap(transform_multiallocation_chain &other_chain) |
| { holder_.swap(other_chain.holder_); } |
| /* |
| void splice_after(iterator after_this, iterator before_begin, iterator before_end) |
| { holder_.splice_after(after_this.base(), before_begin.base(), before_end.base()); } |
| */ |
| void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_begin, iterator before_end, std::size_t n) |
| { holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); } |
| |
| void pop_front() |
| { holder_.pop_front(); } |
| |
| pointer front() const |
| { return cast(holder_.front()); } |
| |
| bool empty() const |
| { return holder_.empty(); } |
| |
| iterator before_begin() const |
| { return iterator(holder_.before_begin()); } |
| |
| iterator begin() const |
| { return iterator(holder_.begin()); } |
| |
| iterator end() const |
| { return iterator(holder_.end()); } |
| |
| iterator last() const |
| { return iterator(holder_.last()); } |
| |
| std::size_t size() const |
| { return holder_.size(); } |
| |
| void clear() |
| { holder_.clear(); } |
| |
| iterator insert_after(iterator it, pointer m) |
| { return iterator(holder_.insert_after(it.base(), m)); } |
| |
| static iterator iterator_to(pointer p) |
| { return iterator(MultiallocationChain::iterator_to(p)); } |
| |
| std::pair<void_pointer, void_pointer> extract_data() |
| { return holder_.extract_data(); } |
| |
| MultiallocationChain extract_multiallocation_chain() |
| { |
| return MultiallocationChain(boost::interprocess::move(holder_)); |
| } |
| }; |
| |
| }}} |
| |
| // namespace containers_detail { |
| // namespace interprocess_container { |
| // namespace boost { |
| |
| #include <boost/interprocess/containers/container/detail/config_end.hpp> |
| |
| #endif //BOOST_CONTAINERS_DETAIL_MULTIALLOCATION_CHAIN_HPP |