boost/interprocess/containers/container/detail/multiallocation_chain.hpp
////////////////////////////////////////////////////////////////////////////// // // (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