555 lines
16 KiB
C++
555 lines
16 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (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
|