1 | /* Copyright 2003-2013 Joaquin M Lopez Munoz. |
2 | * Distributed under the Boost Software License, Version 1.0. |
3 | * (See accompanying file LICENSE_1_0.txt or copy at |
4 | * http://www.boost.org/LICENSE_1_0.txt) |
5 | * |
6 | * See http://www.boost.org/libs/multi_index for library home page. |
7 | */ |
8 | |
9 | #ifndef BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP |
10 | #define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP |
11 | |
12 | #if defined(_MSC_VER) |
13 | #pragma once |
14 | #endif |
15 | |
16 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
17 | #include <algorithm> |
18 | #include <boost/detail/allocator_utilities.hpp> |
19 | #include <boost/multi_index/detail/adl_swap.hpp> |
20 | #include <boost/noncopyable.hpp> |
21 | #include <memory> |
22 | |
23 | namespace boost{ |
24 | |
25 | namespace multi_index{ |
26 | |
27 | namespace detail{ |
28 | |
29 | /* auto_space provides uninitialized space suitably to store |
30 | * a given number of elements of a given type. |
31 | */ |
32 | |
33 | /* NB: it is not clear whether using an allocator to handle |
34 | * zero-sized arrays of elements is conformant or not. GCC 3.3.1 |
35 | * and prior fail here, other stdlibs handle the issue gracefully. |
36 | * To be on the safe side, the case n==0 is given special treatment. |
37 | * References: |
38 | * GCC Bugzilla, "standard allocator crashes when deallocating segment |
39 | * "of zero length", http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14176 |
40 | * C++ Standard Library Defect Report List (Revision 28), issue 199 |
41 | * "What does allocate(0) return?", |
42 | * http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#199 |
43 | */ |
44 | |
45 | template<typename T,typename Allocator=std::allocator<T> > |
46 | struct auto_space:private noncopyable |
47 | { |
48 | typedef typename boost::detail::allocator::rebind_to< |
49 | Allocator,T |
50 | >::type::pointer pointer; |
51 | |
52 | explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1): |
53 | al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0)) |
54 | {} |
55 | |
56 | ~auto_space() |
57 | { |
58 | if(n_)al_.deallocate(data_,n_); |
59 | } |
60 | |
61 | Allocator get_allocator()const{return al_;} |
62 | |
63 | pointer data()const{return data_;} |
64 | |
65 | void swap(auto_space& x) |
66 | { |
67 | if(al_!=x.al_)adl_swap(al_,x.al_); |
68 | std::swap(n_,x.n_); |
69 | std::swap(data_,x.data_); |
70 | } |
71 | |
72 | private: |
73 | typename boost::detail::allocator::rebind_to< |
74 | Allocator,T>::type al_; |
75 | std::size_t n_; |
76 | pointer data_; |
77 | }; |
78 | |
79 | template<typename T,typename Allocator> |
80 | void swap(auto_space<T,Allocator>& x,auto_space<T,Allocator>& y) |
81 | { |
82 | x.swap(y); |
83 | } |
84 | |
85 | } /* namespace multi_index::detail */ |
86 | |
87 | } /* namespace multi_index */ |
88 | |
89 | } /* namespace boost */ |
90 | |
91 | #endif |
92 | |