| |
| // Copyright 2005-2009 Daniel James. |
| // 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) |
| |
| #ifndef BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED |
| #define BOOST_UNORDERED_DETAIL_ALLOCATOR_UTILITIES_HPP_INCLUDED |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
| # pragma once |
| #endif |
| |
| #include <boost/config.hpp> |
| |
| #if (defined(BOOST_NO_STD_ALLOCATOR) || defined(BOOST_DINKUMWARE_STDLIB)) \ |
| && !defined(__BORLANDC__) |
| # define BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES |
| #endif |
| |
| #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) |
| # include <boost/detail/allocator_utilities.hpp> |
| #endif |
| |
| #include <boost/mpl/aux_/config/eti.hpp> |
| |
| namespace boost { |
| namespace unordered_detail { |
| |
| #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) |
| template <class Alloc, class T> |
| struct rebind_wrap : ::boost::detail::allocator::rebind_to<Alloc, T> {}; |
| #else |
| template <class Alloc, class T> |
| struct rebind_wrap |
| { |
| typedef BOOST_DEDUCED_TYPENAME |
| Alloc::BOOST_NESTED_TEMPLATE rebind<T>::other |
| type; |
| }; |
| #endif |
| |
| #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
| template <class T> |
| inline void reset(T& x) { x = T(); } |
| |
| template <class Ptr> |
| inline Ptr null_ptr() { return Ptr(); } |
| #else |
| template <class T> |
| inline void reset_impl(T& x, ...) { x = T(); } |
| template <class T> |
| inline void reset_impl(T*& x, int) { x = 0; } |
| template <class T> |
| inline void reset(T& x) { reset_impl(x); } |
| |
| template <class Ptr> |
| inline Ptr null_ptr() { Ptr x; reset(x); return x; } |
| #endif |
| |
| // Work around for Microsoft's ETI bug. |
| |
| template <class Allocator> struct allocator_value_type |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::value_type type; |
| }; |
| |
| template <class Allocator> struct allocator_pointer |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::pointer type; |
| }; |
| |
| template <class Allocator> struct allocator_const_pointer |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::const_pointer type; |
| }; |
| |
| template <class Allocator> struct allocator_reference |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::reference type; |
| }; |
| |
| template <class Allocator> struct allocator_const_reference |
| { |
| typedef BOOST_DEDUCED_TYPENAME Allocator::const_reference type; |
| }; |
| |
| #if defined(BOOST_MPL_CFG_MSVC_ETI_BUG) |
| |
| template <> |
| struct allocator_value_type<int> |
| { |
| typedef int type; |
| }; |
| |
| template <> |
| struct allocator_pointer<int> |
| { |
| typedef int type; |
| }; |
| |
| template <> |
| struct allocator_const_pointer<int> |
| { |
| typedef int type; |
| }; |
| |
| template <> |
| struct allocator_reference<int> |
| { |
| typedef int type; |
| }; |
| |
| template <> |
| struct allocator_const_reference<int> |
| { |
| typedef int type; |
| }; |
| |
| #endif |
| |
| template <class Allocator> |
| struct allocator_constructor |
| { |
| typedef BOOST_DEDUCED_TYPENAME allocator_value_type<Allocator>::type value_type; |
| typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer; |
| |
| Allocator& alloc_; |
| pointer ptr_; |
| bool constructed_; |
| |
| allocator_constructor(Allocator& a) |
| : alloc_(a), ptr_(), constructed_(false) |
| { |
| #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
| unordered_detail::reset(ptr_); |
| #endif |
| } |
| |
| ~allocator_constructor() { |
| if(ptr_) { |
| if(constructed_) alloc_.destroy(ptr_); |
| alloc_.deallocate(ptr_, 1); |
| } |
| } |
| |
| template <class V> |
| void construct(V const& v) { |
| BOOST_ASSERT(!ptr_ && !constructed_); |
| ptr_ = alloc_.allocate(1); |
| alloc_.construct(ptr_, value_type(v)); |
| constructed_ = true; |
| } |
| |
| void construct(value_type const& v) { |
| BOOST_ASSERT(!ptr_ && !constructed_); |
| ptr_ = alloc_.allocate(1); |
| alloc_.construct(ptr_, v); |
| constructed_ = true; |
| } |
| |
| pointer get() const |
| { |
| return ptr_; |
| } |
| |
| // no throw |
| pointer release() |
| { |
| pointer p = ptr_; |
| constructed_ = false; |
| unordered_detail::reset(ptr_); |
| return p; |
| } |
| }; |
| |
| template <class Allocator> |
| struct allocator_array_constructor |
| { |
| typedef BOOST_DEDUCED_TYPENAME allocator_pointer<Allocator>::type pointer; |
| |
| Allocator& alloc_; |
| pointer ptr_; |
| pointer constructed_; |
| std::size_t length_; |
| |
| allocator_array_constructor(Allocator& a) |
| : alloc_(a), ptr_(), constructed_(), length_(0) |
| { |
| #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
| unordered_detail::reset(constructed_); |
| unordered_detail::reset(ptr_); |
| #endif |
| } |
| |
| ~allocator_array_constructor() { |
| if (ptr_) { |
| for(pointer p = ptr_; p != constructed_; ++p) |
| alloc_.destroy(p); |
| |
| alloc_.deallocate(ptr_, length_); |
| } |
| } |
| |
| template <class V> |
| void construct(V const& v, std::size_t l) |
| { |
| BOOST_ASSERT(!ptr_); |
| length_ = l; |
| ptr_ = alloc_.allocate(length_); |
| pointer end = ptr_ + static_cast<std::ptrdiff_t>(length_); |
| for(constructed_ = ptr_; constructed_ != end; ++constructed_) |
| alloc_.construct(constructed_, v); |
| } |
| |
| pointer get() const |
| { |
| return ptr_; |
| } |
| |
| pointer release() |
| { |
| pointer p(ptr_); |
| unordered_detail::reset(ptr_); |
| return p; |
| } |
| private: |
| allocator_array_constructor(allocator_array_constructor const&); |
| allocator_array_constructor& operator=(allocator_array_constructor const&); |
| }; |
| } |
| } |
| |
| #if defined(BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES) |
| # undef BOOST_UNORDERED_USE_ALLOCATOR_UTILITIES |
| #endif |
| |
| #endif |