diff options
Diffstat (limited to 'boost/container/detail/destroyers.hpp')
-rw-r--r-- | boost/container/detail/destroyers.hpp | 141 |
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 { |