summaryrefslogtreecommitdiff
path: root/boost/container/detail/destroyers.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container/detail/destroyers.hpp')
-rw-r--r--boost/container/detail/destroyers.hpp141
1 files changed, 134 insertions, 7 deletions
diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp
index d1b118cdcc..ea9b617437 100644
--- a/boost/container/detail/destroyers.hpp
+++ b/boost/container/detail/destroyers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -13,12 +13,13 @@
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
#define BOOST_CONTAINER_DESTROYERS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -28,6 +29,74 @@ namespace container {
namespace container_detail {
//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an object using a STL allocator.
+template <class A>
+struct scoped_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef container_detail::integral_constant<unsigned,
+ boost::container::container_detail::
+ version<A>::value> alloc_version;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
+
+ private:
+ void priv_deallocate(allocator_v1)
+ { m_alloc.deallocate(m_ptr, 1); }
+
+ void priv_deallocate(allocator_v2)
+ { m_alloc.deallocate_one(m_ptr); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
+
+ public:
+
+ pointer m_ptr;
+ A& m_alloc;
+
+ scoped_deallocator(pointer p, A& a)
+ : m_ptr(p), m_alloc(a)
+ {}
+
+ ~scoped_deallocator()
+ { if (m_ptr)priv_deallocate(alloc_version()); }
+
+ scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
+ : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
+ { o.release(); }
+
+ pointer get() const
+ { return m_ptr; }
+
+ void set(const pointer &p)
+ { m_ptr = p; }
+
+ void release()
+ { m_ptr = 0; }
+};
+
+template <class Allocator>
+struct null_scoped_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_deallocator(pointer, Allocator&, size_type)
+ {}
+
+ void release()
+ {}
+
+ pointer get() const
+ { return pointer(); }
+
+ void set(const pointer &)
+ {}
+};
+
+//!A deleter for scoped_ptr that deallocates the memory
//!allocated for an array of objects using a STL allocator.
template <class Allocator>
struct scoped_array_deallocator
@@ -126,13 +195,17 @@ struct scoped_destructor_n
void increment_size_backwards(size_type inc)
{ m_n += inc; m_p -= inc; }
-
+
+ void shrink_forward(size_type inc)
+ { m_n -= inc; m_p += inc; }
+
~scoped_destructor_n()
{
if(!m_p) return;
value_type *raw_ptr = container_detail::to_raw_pointer(m_p);
- for(size_type i = 0; i < m_n; ++i, ++raw_ptr)
- AllocTraits::destroy(m_a, raw_ptr);
+ while(m_n--){
+ AllocTraits::destroy(m_a, raw_ptr++);
+ }
}
private:
@@ -159,6 +232,9 @@ struct null_scoped_destructor_n
void increment_size_backwards(size_type)
{}
+ void shrink_forward(size_type)
+ {}
+
void release()
{}
};
@@ -183,6 +259,11 @@ class scoped_destructor
void release()
{ pv_ = 0; }
+
+ void set(value_type *ptr) { pv_ = ptr; }
+
+ value_type *get() const { return pv_; }
+
private:
value_type *pv_;
A &a_;
@@ -239,10 +320,56 @@ class allocator_destroyer
void operator()(const pointer &p)
{
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
- priv_deallocate(p, alloc_version());
+ this->priv_deallocate(p, alloc_version());
}
};
+template <class A>
+class allocator_destroyer_and_chain_builder
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+
+ A & a_;
+ multiallocation_chain &c_;
+
+ public:
+ allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
+ : a_(a), c_(c)
+ {}
+
+ void operator()(const typename A::pointer &p)
+ {
+ allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
+ c_.push_back(p);
+ }
+};
+
+template <class A>
+class allocator_multialloc_chain_node_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+ typedef allocator_destroyer_and_chain_builder<A> chain_builder;
+
+ A & a_;
+ multiallocation_chain c_;
+
+ public:
+ allocator_multialloc_chain_node_deallocator(A &a)
+ : a_(a), c_()
+ {}
+
+ chain_builder get_chain_builder()
+ { return chain_builder(a_, c_); }
+
+ ~allocator_multialloc_chain_node_deallocator()
+ {
+ a_.deallocate_individual(c_);
+ }
+};
} //namespace container_detail {
} //namespace container {