libstdc++
stl_tempbuf.h
Go to the documentation of this file.
1 // Temporary buffer implementation -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4 // 2010, 2011
5 // Free Software Foundation, Inc.
6 //
7 // This file is part of the GNU ISO C++ Library. This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12 
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
21 
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 // <http://www.gnu.org/licenses/>.
26 
27 /*
28  *
29  * Copyright (c) 1994
30  * Hewlett-Packard Company
31  *
32  * Permission to use, copy, modify, distribute and sell this software
33  * and its documentation for any purpose is hereby granted without fee,
34  * provided that the above copyright notice appear in all copies and
35  * that both that copyright notice and this permission notice appear
36  * in supporting documentation. Hewlett-Packard Company makes no
37  * representations about the suitability of this software for any
38  * purpose. It is provided "as is" without express or implied warranty.
39  *
40  *
41  * Copyright (c) 1996,1997
42  * Silicon Graphics Computer Systems, Inc.
43  *
44  * Permission to use, copy, modify, distribute and sell this software
45  * and its documentation for any purpose is hereby granted without fee,
46  * provided that the above copyright notice appear in all copies and
47  * that both that copyright notice and this permission notice appear
48  * in supporting documentation. Silicon Graphics makes no
49  * representations about the suitability of this software for any
50  * purpose. It is provided "as is" without express or implied warranty.
51  */
52 
53 /** @file bits/stl_tempbuf.h
54  * This is an internal header file, included by other library headers.
55  * Do not attempt to use it directly. @headername{memory}
56  */
57 
58 #ifndef _STL_TEMPBUF_H
59 #define _STL_TEMPBUF_H 1
60 
61 #include <bits/stl_algobase.h>
62 #include <bits/stl_construct.h>
63 
64 namespace std _GLIBCXX_VISIBILITY(default)
65 {
66 _GLIBCXX_BEGIN_NAMESPACE_VERSION
67 
68  /**
69  * @brief Allocates a temporary buffer.
70  * @param __len The number of objects of type Tp.
71  * @return See full description.
72  *
73  * Reinventing the wheel, but this time with prettier spokes!
74  *
75  * This function tries to obtain storage for @c __len adjacent Tp
76  * objects. The objects themselves are not constructed, of course.
77  * A pair<> is returned containing <em>the buffer s address and
78  * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
79  * no storage can be obtained.</em> Note that the capacity obtained
80  * may be less than that requested if the memory is unavailable;
81  * you should compare len with the .second return value.
82  *
83  * Provides the nothrow exception guarantee.
84  */
85  template<typename _Tp>
86  pair<_Tp*, ptrdiff_t>
87  get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
88  {
89  const ptrdiff_t __max =
90  __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
91  if (__len > __max)
92  __len = __max;
93 
94  while (__len > 0)
95  {
96  _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
97  std::nothrow));
98  if (__tmp != 0)
99  return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
100  __len /= 2;
101  }
102  return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
103  }
104 
105  /**
106  * @brief The companion to get_temporary_buffer().
107  * @param __p A buffer previously allocated by get_temporary_buffer.
108  * @return None.
109  *
110  * Frees the memory pointed to by __p.
111  */
112  template<typename _Tp>
113  inline void
115  { ::operator delete(__p, std::nothrow); }
116 
117 
118  /**
119  * This class is used in two places: stl_algo.h and ext/memory,
120  * where it is wrapped as the temporary_buffer class. See
121  * temporary_buffer docs for more notes.
122  */
123  template<typename _ForwardIterator, typename _Tp>
125  {
126  // concept requirements
127  __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
128 
129  public:
130  typedef _Tp value_type;
131  typedef value_type* pointer;
132  typedef pointer iterator;
133  typedef ptrdiff_t size_type;
134 
135  protected:
136  size_type _M_original_len;
137  size_type _M_len;
138  pointer _M_buffer;
139 
140  public:
141  /// As per Table mumble.
142  size_type
143  size() const
144  { return _M_len; }
145 
146  /// Returns the size requested by the constructor; may be >size().
147  size_type
149  { return _M_original_len; }
150 
151  /// As per Table mumble.
152  iterator
154  { return _M_buffer; }
155 
156  /// As per Table mumble.
157  iterator
158  end()
159  { return _M_buffer + _M_len; }
160 
161  /**
162  * Constructs a temporary buffer of a size somewhere between
163  * zero and the size of the given range.
164  */
165  _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last);
166 
168  {
169  std::_Destroy(_M_buffer, _M_buffer + _M_len);
170  std::return_temporary_buffer(_M_buffer);
171  }
172 
173  private:
174  // Disable copy constructor and assignment operator.
176 
177  void
178  operator=(const _Temporary_buffer&);
179  };
180 
181 
182  template<bool>
183  struct __uninitialized_construct_buf_dispatch
184  {
185  template<typename _ForwardIterator, typename _Tp>
186  static void
187  __ucr(_ForwardIterator __first, _ForwardIterator __last,
188  _Tp& __value)
189  {
190  if(__first == __last)
191  return;
192 
193  _ForwardIterator __cur = __first;
194  __try
195  {
197  _GLIBCXX_MOVE(__value));
198  _ForwardIterator __prev = __cur;
199  ++__cur;
200  for(; __cur != __last; ++__cur, ++__prev)
202  _GLIBCXX_MOVE(*__prev));
203  __value = _GLIBCXX_MOVE(*__prev);
204  }
205  __catch(...)
206  {
207  std::_Destroy(__first, __cur);
208  __throw_exception_again;
209  }
210  }
211  };
212 
213  template<>
214  struct __uninitialized_construct_buf_dispatch<true>
215  {
216  template<typename _ForwardIterator, typename _Tp>
217  static void
218  __ucr(_ForwardIterator, _ForwardIterator, _Tp&) { }
219  };
220 
221  // Constructs objects in the range [first, last).
222  // Note that while these new objects will take valid values,
223  // their exact value is not defined. In particular they may
224  // be 'moved from'.
225  //
226  // While __value may altered during this algorithm, it will have
227  // the same value when the algorithm finishes, unless one of the
228  // constructions throws.
229  //
230  // Requirements: _ForwardIterator::value_type(_Tp&&) is valid.
231  template<typename _ForwardIterator, typename _Tp>
232  inline void
233  __uninitialized_construct_buf(_ForwardIterator __first,
234  _ForwardIterator __last,
235  _Tp& __value)
236  {
237  typedef typename std::iterator_traits<_ForwardIterator>::value_type
238  _ValueType;
239 
240  std::__uninitialized_construct_buf_dispatch<
241  __has_trivial_constructor(_ValueType)>::
242  __ucr(__first, __last, __value);
243  }
244 
245  template<typename _ForwardIterator, typename _Tp>
247  _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last)
248  : _M_original_len(std::distance(__first, __last)),
249  _M_len(0), _M_buffer(0)
250  {
251  __try
252  {
254  value_type>(_M_original_len));
255  _M_buffer = __p.first;
256  _M_len = __p.second;
257  if(_M_buffer)
258  std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len,
259  *__first);
260  }
261  __catch(...)
262  {
263  std::return_temporary_buffer(_M_buffer);
264  _M_buffer = 0;
265  _M_len = 0;
266  __throw_exception_again;
267  }
268  }
269 
270 _GLIBCXX_END_NAMESPACE_VERSION
271 } // namespace
272 
273 #endif /* _STL_TEMPBUF_H */
274