Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of boost. Click here for the latest Boost documentation.

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